Commit 235b8cbc authored by mharanczyk's avatar mharanczyk Committed by Commit bot

Expose final download URL (actual url after redirects) in the extension API.

BUG=620630

Review-Url: https://codereview.chromium.org/1706193002
Cr-Commit-Position: refs/heads/master@{#404619}
parent 762c2ebc
...@@ -70,11 +70,11 @@ template<> bool GetAs(const base::Value& in, std::vector<base::string16>* out) { ...@@ -70,11 +70,11 @@ template<> bool GetAs(const base::Value& in, std::vector<base::string16>* out) {
// The next several functions are helpers for making Callbacks that access // The next several functions are helpers for making Callbacks that access
// DownloadItem fields. // DownloadItem fields.
static int64_t GetStartTimeMsEpoch(const DownloadItem& item) { int64_t GetStartTimeMsEpoch(const DownloadItem& item) {
return (item.GetStartTime() - base::Time::UnixEpoch()).InMilliseconds(); return (item.GetStartTime() - base::Time::UnixEpoch()).InMilliseconds();
} }
static int64_t GetEndTimeMsEpoch(const DownloadItem& item) { int64_t GetEndTimeMsEpoch(const DownloadItem& item) {
return (item.GetEndTime() - base::Time::UnixEpoch()).InMilliseconds(); return (item.GetEndTime() - base::Time::UnixEpoch()).InMilliseconds();
} }
...@@ -87,58 +87,62 @@ std::string TimeToISO8601(const base::Time& t) { ...@@ -87,58 +87,62 @@ std::string TimeToISO8601(const base::Time& t) {
exploded.millisecond); exploded.millisecond);
} }
static std::string GetStartTime(const DownloadItem& item) { std::string GetStartTime(const DownloadItem& item) {
return TimeToISO8601(item.GetStartTime()); return TimeToISO8601(item.GetStartTime());
} }
static std::string GetEndTime(const DownloadItem& item) { std::string GetEndTime(const DownloadItem& item) {
return TimeToISO8601(item.GetEndTime()); return TimeToISO8601(item.GetEndTime());
} }
static bool GetDangerAccepted(const DownloadItem& item) { bool GetDangerAccepted(const DownloadItem& item) {
return (item.GetDangerType() == return (item.GetDangerType() ==
content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED);
} }
static bool GetExists(const DownloadItem& item) { bool GetExists(const DownloadItem& item) {
return !item.GetFileExternallyRemoved(); return !item.GetFileExternallyRemoved();
} }
static base::string16 GetFilename(const DownloadItem& item) { base::string16 GetFilename(const DownloadItem& item) {
// This filename will be compared with strings that could be passed in by the // This filename will be compared with strings that could be passed in by the
// user, who only sees LossyDisplayNames. // user, who only sees LossyDisplayNames.
return item.GetTargetFilePath().LossyDisplayName(); return item.GetTargetFilePath().LossyDisplayName();
} }
static std::string GetFilenameUTF8(const DownloadItem& item) { std::string GetFilenameUTF8(const DownloadItem& item) {
return base::UTF16ToUTF8(GetFilename(item)); return base::UTF16ToUTF8(GetFilename(item));
} }
static std::string GetUrl(const DownloadItem& item) { std::string GetOriginalUrl(const DownloadItem& item) {
return item.GetOriginalUrl().spec(); return item.GetOriginalUrl().spec();
} }
static DownloadItem::DownloadState GetState(const DownloadItem& item) { std::string GetUrl(const DownloadItem& item) {
return item.GetURL().spec();
}
DownloadItem::DownloadState GetState(const DownloadItem& item) {
return item.GetState(); return item.GetState();
} }
static DownloadDangerType GetDangerType(const DownloadItem& item) { DownloadDangerType GetDangerType(const DownloadItem& item) {
return item.GetDangerType(); return item.GetDangerType();
} }
static double GetReceivedBytes(const DownloadItem& item) { double GetReceivedBytes(const DownloadItem& item) {
return item.GetReceivedBytes(); return item.GetReceivedBytes();
} }
static double GetTotalBytes(const DownloadItem& item) { double GetTotalBytes(const DownloadItem& item) {
return item.GetTotalBytes(); return item.GetTotalBytes();
} }
static std::string GetMimeType(const DownloadItem& item) { std::string GetMimeType(const DownloadItem& item) {
return item.GetMimeType(); return item.GetMimeType();
} }
static bool IsPaused(const DownloadItem& item) { bool IsPaused(const DownloadItem& item) {
return item.IsPaused(); return item.IsPaused();
} }
...@@ -149,7 +153,7 @@ enum ComparisonType {LT, EQ, GT}; ...@@ -149,7 +153,7 @@ enum ComparisonType {LT, EQ, GT};
// DownloadItem and returns one of its fields, which is then compared to // DownloadItem and returns one of its fields, which is then compared to
// |value|. // |value|.
template<typename ValueType> template<typename ValueType>
static bool FieldMatches( bool FieldMatches(
const ValueType& value, const ValueType& value,
ComparisonType cmptype, ComparisonType cmptype,
const base::Callback<ValueType(const DownloadItem&)>& accessor, const base::Callback<ValueType(const DownloadItem&)>& accessor,
...@@ -174,7 +178,7 @@ template <typename ValueType> DownloadQuery::FilterCallback BuildFilter( ...@@ -174,7 +178,7 @@ template <typename ValueType> DownloadQuery::FilterCallback BuildFilter(
} }
// Returns true if |accessor.Run(item)| matches |pattern|. // Returns true if |accessor.Run(item)| matches |pattern|.
static bool FindRegex( bool FindRegex(
RE2* pattern, RE2* pattern,
const base::Callback<std::string(const DownloadItem&)>& accessor, const base::Callback<std::string(const DownloadItem&)>& accessor,
const DownloadItem& item) { const DownloadItem& item) {
...@@ -196,7 +200,7 @@ DownloadQuery::FilterCallback BuildRegexFilter( ...@@ -196,7 +200,7 @@ DownloadQuery::FilterCallback BuildRegexFilter(
// Returns a ComparisonType to indicate whether a field in |left| is less than, // Returns a ComparisonType to indicate whether a field in |left| is less than,
// greater than or equal to the same field in |right|. // greater than or equal to the same field in |right|.
template<typename ValueType> template<typename ValueType>
static ComparisonType Compare( ComparisonType Compare(
const base::Callback<ValueType(const DownloadItem&)>& accessor, const base::Callback<ValueType(const DownloadItem&)>& accessor,
const DownloadItem& left, const DownloadItem& right) { const DownloadItem& left, const DownloadItem& right) {
ValueType left_value = accessor.Run(left); ValueType left_value = accessor.Run(left);
...@@ -215,16 +219,27 @@ bool DownloadQuery::MatchesQuery(const std::vector<base::string16>& query_terms, ...@@ -215,16 +219,27 @@ bool DownloadQuery::MatchesQuery(const std::vector<base::string16>& query_terms,
if (query_terms.empty()) if (query_terms.empty())
return true; return true;
base::string16 url_raw(base::UTF8ToUTF16(item.GetOriginalUrl().spec())); base::string16 original_url_raw(
base::string16 url_formatted = url_raw; base::UTF8ToUTF16(item.GetOriginalUrl().spec()));
if (item.GetBrowserContext()) base::string16 url_raw(base::UTF8ToUTF16(item.GetURL().spec()));
url_formatted = url_formatter::FormatUrl(item.GetOriginalUrl()); // Try to also match query with above URLs formatted in user display friendly
// way. This will unescape characters (including spaces) and trim all extra
// data (like username and password) from raw url so that for example raw url
// "http://some.server.org/example%20download/file.zip" will be matched with
// search term "example download".
base::string16 original_url_formatted(
url_formatter::FormatUrl(item.GetOriginalUrl()));
base::string16 url_formatted(url_formatter::FormatUrl(item.GetURL()));
base::string16 path(item.GetTargetFilePath().LossyDisplayName()); base::string16 path(item.GetTargetFilePath().LossyDisplayName());
for (std::vector<base::string16>::const_iterator it = query_terms.begin(); for (std::vector<base::string16>::const_iterator it = query_terms.begin();
it != query_terms.end(); ++it) { it != query_terms.end(); ++it) {
base::string16 term = base::i18n::ToLower(*it); base::string16 term = base::i18n::ToLower(*it);
if (!base::i18n::StringSearchIgnoringCaseAndAccents( if (!base::i18n::StringSearchIgnoringCaseAndAccents(
term, original_url_raw, NULL, NULL) &&
!base::i18n::StringSearchIgnoringCaseAndAccents(
term, original_url_formatted, NULL, NULL) &&
!base::i18n::StringSearchIgnoringCaseAndAccents(
term, url_raw, NULL, NULL) && term, url_raw, NULL, NULL) &&
!base::i18n::StringSearchIgnoringCaseAndAccents( !base::i18n::StringSearchIgnoringCaseAndAccents(
term, url_formatted, NULL, NULL) && term, url_formatted, NULL, NULL) &&
...@@ -301,6 +316,10 @@ bool DownloadQuery::AddFilter(DownloadQuery::FilterType type, ...@@ -301,6 +316,10 @@ bool DownloadQuery::AddFilter(DownloadQuery::FilterType type,
return AddFilter(BuildFilter<double>(value, GT, &GetTotalBytes)); return AddFilter(BuildFilter<double>(value, GT, &GetTotalBytes));
case FILTER_TOTAL_BYTES_LESS: case FILTER_TOTAL_BYTES_LESS:
return AddFilter(BuildFilter<double>(value, LT, &GetTotalBytes)); return AddFilter(BuildFilter<double>(value, LT, &GetTotalBytes));
case FILTER_ORIGINAL_URL:
return AddFilter(BuildFilter<std::string>(value, EQ, &GetOriginalUrl));
case FILTER_ORIGINAL_URL_REGEX:
return AddFilter(BuildRegexFilter(value, &GetOriginalUrl));
case FILTER_URL: case FILTER_URL:
return AddFilter(BuildFilter<std::string>(value, EQ, &GetUrl)); return AddFilter(BuildFilter<std::string>(value, EQ, &GetUrl));
case FILTER_URL_REGEX: case FILTER_URL_REGEX:
...@@ -391,6 +410,10 @@ void DownloadQuery::AddSorter(DownloadQuery::SortType type, ...@@ -391,6 +410,10 @@ void DownloadQuery::AddSorter(DownloadQuery::SortType type,
sorters_.push_back( sorters_.push_back(
Sorter::Build<int64_t>(direction, &GetStartTimeMsEpoch)); Sorter::Build<int64_t>(direction, &GetStartTimeMsEpoch));
break; break;
case SORT_ORIGINAL_URL:
sorters_.push_back(
Sorter::Build<std::string>(direction, &GetOriginalUrl));
break;
case SORT_URL: case SORT_URL:
sorters_.push_back(Sorter::Build<std::string>(direction, &GetUrl)); sorters_.push_back(Sorter::Build<std::string>(direction, &GetUrl));
break; break;
......
...@@ -69,6 +69,8 @@ class DownloadQuery { ...@@ -69,6 +69,8 @@ class DownloadQuery {
FILTER_TOTAL_BYTES, // double FILTER_TOTAL_BYTES, // double
FILTER_TOTAL_BYTES_GREATER, // double FILTER_TOTAL_BYTES_GREATER, // double
FILTER_TOTAL_BYTES_LESS, // double FILTER_TOTAL_BYTES_LESS, // double
FILTER_ORIGINAL_URL, // string
FILTER_ORIGINAL_URL_REGEX, // string
FILTER_URL, // string FILTER_URL, // string
FILTER_URL_REGEX, // string FILTER_URL_REGEX, // string
}; };
...@@ -85,6 +87,7 @@ class DownloadQuery { ...@@ -85,6 +87,7 @@ class DownloadQuery {
SORT_START_TIME, SORT_START_TIME,
SORT_STATE, SORT_STATE,
SORT_TOTAL_BYTES, SORT_TOTAL_BYTES,
SORT_ORIGINAL_URL,
SORT_URL, SORT_URL,
}; };
......
...@@ -204,13 +204,15 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryFilename) { ...@@ -204,13 +204,15 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryFilename) {
GURL fail_url("http://example.com/fail"); GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
std::vector<std::string> query_terms; std::vector<std::string> query_terms;
query_terms.push_back("query"); query_terms.push_back("query");
AddFilter(DownloadQuery::FILTER_QUERY, query_terms); AddFilter(DownloadQuery::FILTER_QUERY, query_terms);
ExpectStandardFilterResults(); ExpectStandardFilterResults();
} }
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryUrl) { TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryOriginalUrl) {
CreateMocks(2); CreateMocks(2);
EXPECT_CALL(mock(0), GetBrowserContext()).WillRepeatedly(Return( EXPECT_CALL(mock(0), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL))); static_cast<content::BrowserContext*>(NULL)));
...@@ -225,6 +227,78 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryUrl) { ...@@ -225,6 +227,78 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryUrl) {
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url)); EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url));
GURL fail_url("http://example.com/fail"); GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
std::vector<std::string> query_terms;
query_terms.push_back("query");
AddFilter(DownloadQuery::FILTER_QUERY, query_terms);
ExpectStandardFilterResults();
}
TEST_F(DownloadQueryTest,
DownloadQueryTest_FilterGenericQueryOriginalUrlUnescaping) {
CreateMocks(2);
EXPECT_CALL(mock(0), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL)));
EXPECT_CALL(mock(1), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL)));
base::FilePath fail_filename(FILE_PATH_LITERAL("fail"));
EXPECT_CALL(mock(0), GetTargetFilePath()).WillRepeatedly(ReturnRef(
fail_filename));
EXPECT_CALL(mock(1), GetTargetFilePath()).WillRepeatedly(ReturnRef(
fail_filename));
GURL match_url("http://q%75%65%72y.c%6Fm/%71uer%79");
GURL fail_url("http://%65xampl%65.com/%66ai%6C");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url));
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
std::vector<std::string> query_terms;
query_terms.push_back("query");
AddFilter(DownloadQuery::FILTER_QUERY, query_terms);
ExpectStandardFilterResults();
}
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryUrl) {
CreateMocks(2);
EXPECT_CALL(mock(0), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL)));
EXPECT_CALL(mock(1), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL)));
base::FilePath fail_filename(FILE_PATH_LITERAL("fail"));
EXPECT_CALL(mock(0), GetTargetFilePath()).WillRepeatedly(ReturnRef(
fail_filename));
EXPECT_CALL(mock(1), GetTargetFilePath()).WillRepeatedly(ReturnRef(
fail_filename));
GURL match_url("http://query.com/query");
GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(match_url));
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
std::vector<std::string> query_terms;
query_terms.push_back("query");
AddFilter(DownloadQuery::FILTER_QUERY, query_terms);
ExpectStandardFilterResults();
}
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryUrlUnescaping) {
CreateMocks(2);
EXPECT_CALL(mock(0), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL)));
EXPECT_CALL(mock(1), GetBrowserContext()).WillRepeatedly(Return(
static_cast<content::BrowserContext*>(NULL)));
base::FilePath fail_filename(FILE_PATH_LITERAL("fail"));
EXPECT_CALL(mock(0), GetTargetFilePath()).WillRepeatedly(ReturnRef(
fail_filename));
EXPECT_CALL(mock(1), GetTargetFilePath()).WillRepeatedly(ReturnRef(
fail_filename));
GURL match_url("http://%71uer%79.com/qu%65ry");
GURL fail_url("http://e%78am%70le.com/f%61il");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(match_url));
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
std::vector<std::string> query_terms; std::vector<std::string> query_terms;
query_terms.push_back("query"); query_terms.push_back("query");
AddFilter(DownloadQuery::FILTER_QUERY, query_terms); AddFilter(DownloadQuery::FILTER_QUERY, query_terms);
...@@ -253,6 +327,8 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryFilenameI18N) { ...@@ -253,6 +327,8 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterGenericQueryFilenameI18N) {
GURL fail_url("http://example.com/fail"); GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(fail_url));
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
std::vector<base::FilePath::StringType> query_terms; std::vector<base::FilePath::StringType> query_terms;
query_terms.push_back(kTestString); query_terms.push_back(kTestString);
AddFilter(DownloadQuery::FILTER_QUERY, query_terms); AddFilter(DownloadQuery::FILTER_QUERY, query_terms);
...@@ -295,32 +371,63 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterFilename) { ...@@ -295,32 +371,63 @@ TEST_F(DownloadQueryTest, DownloadQueryTest_FilterFilename) {
ExpectStandardFilterResults(); ExpectStandardFilterResults();
} }
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterUrlRegex) { TEST_F(DownloadQueryTest, DownloadQueryTest_FilterOriginalUrlRegex) {
CreateMocks(2); CreateMocks(2);
GURL match_url("http://query.com/query"); GURL match_url("http://query.com/query");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url)); EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url));
GURL fail_url("http://example.com/fail"); GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
AddFilter(DownloadQuery::FILTER_URL_REGEX, "query"); AddFilter(DownloadQuery::FILTER_ORIGINAL_URL_REGEX, "query");
ExpectStandardFilterResults(); ExpectStandardFilterResults();
} }
TEST_F(DownloadQueryTest, DownloadQueryTest_SortUrl) { TEST_F(DownloadQueryTest, DownloadQueryTest_SortOriginalUrl) {
CreateMocks(2); CreateMocks(2);
GURL b_url("http://example.com/b"); GURL b_url("http://example.com/b");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(b_url)); EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(b_url));
GURL a_url("http://example.com/a"); GURL a_url("http://example.com/a");
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(a_url)); EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(a_url));
query()->AddSorter(DownloadQuery::SORT_URL, DownloadQuery::ASCENDING); query()->AddSorter(
DownloadQuery::SORT_ORIGINAL_URL, DownloadQuery::ASCENDING);
ExpectSortInverted(); ExpectSortInverted();
} }
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterUrl) { TEST_F(DownloadQueryTest, DownloadQueryTest_FilterOriginalUrl) {
CreateMocks(2); CreateMocks(2);
GURL match_url("http://query.com/query"); GURL match_url("http://query.com/query");
EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url)); EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(match_url));
GURL fail_url("http://example.com/fail"); GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url)); EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(fail_url));
AddFilter(DownloadQuery::FILTER_ORIGINAL_URL, match_url.spec().c_str());
ExpectStandardFilterResults();
}
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterUrlRegex) {
CreateMocks(2);
GURL match_url("http://query.com/query");
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(match_url));
GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
AddFilter(DownloadQuery::FILTER_URL_REGEX, "query");
ExpectStandardFilterResults();
}
TEST_F(DownloadQueryTest, DownloadQueryTest_SortUrl) {
CreateMocks(2);
GURL b_url("http://example.com/b");
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(b_url));
GURL a_url("http://example.com/a");
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(a_url));
query()->AddSorter(DownloadQuery::SORT_URL, DownloadQuery::ASCENDING);
ExpectSortInverted();
}
TEST_F(DownloadQueryTest, DownloadQueryTest_FilterUrl) {
CreateMocks(2);
GURL match_url("http://query.com/query");
EXPECT_CALL(mock(0), GetURL()).WillRepeatedly(ReturnRef(match_url));
GURL fail_url("http://example.com/fail");
EXPECT_CALL(mock(1), GetURL()).WillRepeatedly(ReturnRef(fail_url));
AddFilter(DownloadQuery::FILTER_URL, match_url.spec().c_str()); AddFilter(DownloadQuery::FILTER_URL, match_url.spec().c_str());
ExpectStandardFilterResults(); ExpectStandardFilterResults();
} }
......
...@@ -173,6 +173,8 @@ const char kTotalBytesKey[] = "totalBytes"; ...@@ -173,6 +173,8 @@ const char kTotalBytesKey[] = "totalBytes";
const char kTotalBytesLessKey[] = "totalBytesLess"; const char kTotalBytesLessKey[] = "totalBytesLess";
const char kUrlKey[] = "url"; const char kUrlKey[] = "url";
const char kUrlRegexKey[] = "urlRegex"; const char kUrlRegexKey[] = "urlRegex";
const char kFinalUrlKey[] = "finalUrl";
const char kFinalUrlRegexKey[] = "finalUrlRegex";
// Note: Any change to the danger type strings, should be accompanied by a // Note: Any change to the danger type strings, should be accompanied by a
// corresponding change to downloads.json. // corresponding change to downloads.json.
...@@ -254,6 +256,9 @@ std::unique_ptr<base::DictionaryValue> DownloadItemToJSON( ...@@ -254,6 +256,9 @@ std::unique_ptr<base::DictionaryValue> DownloadItemToJSON(
json->SetInteger(kIdKey, download_item->GetId()); json->SetInteger(kIdKey, download_item->GetId());
const GURL& url = download_item->GetOriginalUrl(); const GURL& url = download_item->GetOriginalUrl();
json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string())); json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string()));
const GURL& finalUrl = download_item->GetURL();
json->SetString(kFinalUrlKey,
(finalUrl.is_valid() ? finalUrl.spec() : std::string()));
const GURL& referrer = download_item->GetReferrerUrl(); const GURL& referrer = download_item->GetReferrerUrl();
json->SetString(kReferrerUrlKey, (referrer.is_valid() ? referrer.spec() json->SetString(kReferrerUrlKey, (referrer.is_valid() ? referrer.spec()
: std::string())); : std::string()));
...@@ -375,8 +380,10 @@ void InitFilterTypeMap(FilterTypeMap* filter_types_ptr) { ...@@ -375,8 +380,10 @@ void InitFilterTypeMap(FilterTypeMap* filter_types_ptr) {
filter_types[kTotalBytesGreaterKey] = filter_types[kTotalBytesGreaterKey] =
DownloadQuery::FILTER_TOTAL_BYTES_GREATER; DownloadQuery::FILTER_TOTAL_BYTES_GREATER;
filter_types[kTotalBytesLessKey] = DownloadQuery::FILTER_TOTAL_BYTES_LESS; filter_types[kTotalBytesLessKey] = DownloadQuery::FILTER_TOTAL_BYTES_LESS;
filter_types[kUrlKey] = DownloadQuery::FILTER_URL; filter_types[kUrlKey] = DownloadQuery::FILTER_ORIGINAL_URL;
filter_types[kUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX; filter_types[kUrlRegexKey] = DownloadQuery::FILTER_ORIGINAL_URL_REGEX;
filter_types[kFinalUrlKey] = DownloadQuery::FILTER_URL;
filter_types[kFinalUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX;
} }
typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap; typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap;
...@@ -393,7 +400,8 @@ void InitSortTypeMap(SortTypeMap* sorter_types_ptr) { ...@@ -393,7 +400,8 @@ void InitSortTypeMap(SortTypeMap* sorter_types_ptr) {
sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME; sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME;
sorter_types[kStateKey] = DownloadQuery::SORT_STATE; sorter_types[kStateKey] = DownloadQuery::SORT_STATE;
sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES; sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES;
sorter_types[kUrlKey] = DownloadQuery::SORT_URL; sorter_types[kUrlKey] = DownloadQuery::SORT_ORIGINAL_URL;
sorter_types[kFinalUrlKey] = DownloadQuery::SORT_URL;
} }
bool IsNotTemporaryDownloadFilter(const DownloadItem& download_item) { bool IsNotTemporaryDownloadFilter(const DownloadItem& download_item) {
...@@ -906,6 +914,7 @@ bool InvalidId(DownloadItem* valid_item, std::string* message_out) { ...@@ -906,6 +914,7 @@ bool InvalidId(DownloadItem* valid_item, std::string* message_out) {
bool IsDownloadDeltaField(const std::string& field) { bool IsDownloadDeltaField(const std::string& field) {
return ((field == kUrlKey) || return ((field == kUrlKey) ||
(field == kFinalUrlKey) ||
(field == kFilenameKey) || (field == kFilenameKey) ||
(field == kDangerKey) || (field == kDangerKey) ||
(field == kMimeKey) || (field == kMimeKey) ||
......
...@@ -1518,7 +1518,9 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, ...@@ -1518,7 +1518,9 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
" \"incognito\": false," " \"incognito\": false,"
" \"mime\": \"text/plain\"," " \"mime\": \"text/plain\","
" \"paused\": false," " \"paused\": false,"
" \"finalUrl\": \"%s\","
" \"url\": \"%s\"}]", " \"url\": \"%s\"}]",
download_url.c_str(),
download_url.c_str()))); download_url.c_str())));
ASSERT_TRUE( ASSERT_TRUE(
WaitFor(downloads::OnChanged::kEventName, WaitFor(downloads::OnChanged::kEventName,
...@@ -1536,6 +1538,57 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, ...@@ -1536,6 +1538,57 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
result_id))); result_id)));
} }
// Test that we can start a download that gets redirected and that the correct
// sequence of events is fired for it.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
DownloadExtensionTest_Download_Redirect) {
LoadExtension("downloads_split");
ASSERT_TRUE(StartEmbeddedTestServer());
GURL download_final_url(embedded_test_server()->GetURL("/slow?0"));
GURL download_url(embedded_test_server()->GetURL(
"/server-redirect?" + download_final_url.spec()));
GoOnTheRecord();
// Start downloading a file.
std::unique_ptr<base::Value> result(RunFunctionAndReturnResult(
new DownloadsDownloadFunction(),
base::StringPrintf("[{\"url\": \"%s\"}]", download_url.spec().c_str())));
ASSERT_TRUE(result.get());
int result_id = -1;
ASSERT_TRUE(result->GetAsInteger(&result_id));
DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
ASSERT_TRUE(item);
ScopedCancellingItem canceller(item);
ASSERT_EQ(download_url, item->GetOriginalUrl());
ASSERT_EQ(GetExtensionURL(), item->GetSiteUrl().spec());
ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
base::StringPrintf(
"[{\"danger\": \"safe\","
" \"incognito\": false,"
" \"mime\": \"text/plain\","
" \"paused\": false,"
" \"finalUrl\": \"%s\","
" \"url\": \"%s\"}]",
download_final_url.spec().c_str(),
download_url.spec().c_str())));
ASSERT_TRUE(
WaitFor(downloads::OnChanged::kEventName,
base::StringPrintf("[{\"id\": %d,"
" \"filename\": {"
" \"previous\": \"\","
" \"current\": \"%s\"}}]",
result_id, GetFilename("slow.txt").c_str())));
ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
base::StringPrintf(
"[{\"id\": %d,"
" \"state\": {"
" \"previous\": \"in_progress\","
" \"current\": \"complete\"}}]",
result_id)));
}
// Test that we can start a download from an incognito context, and that the // Test that we can start a download from an incognito context, and that the
// download knows that it's incognito. // download knows that it's incognito.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
......
...@@ -134,9 +134,14 @@ namespace downloads { ...@@ -134,9 +134,14 @@ namespace downloads {
// An identifier that is persistent across browser sessions. // An identifier that is persistent across browser sessions.
long id; long id;
// Absolute URL. // The absolute URL that this download initiated from, before any
// redirects.
DOMString url; DOMString url;
// The absolute URL that this download is being made from, after all
// redirects.
DOMString finalUrl;
// Absolute URL. // Absolute URL.
DOMString referrer; DOMString referrer;
...@@ -226,9 +231,9 @@ namespace downloads { ...@@ -226,9 +231,9 @@ namespace downloads {
[inline_doc] dictionary DownloadQuery { [inline_doc] dictionary DownloadQuery {
// This array of search terms limits results to $(ref:DownloadItem) whose // This array of search terms limits results to $(ref:DownloadItem) whose
// <code>filename</code> or <code>url</code> contain all of the search terms // <code>filename</code> or <code>url</code> or <code>finalUrl</code>
// that do not begin with a dash '-' and none of the search terms that do // contain all of the search terms that do not begin with a dash '-' and
// begin with a dash. // none of the search terms that do begin with a dash.
DOMString[]? query; DOMString[]? query;
// Limits results to $(ref:DownloadItem) that // Limits results to $(ref:DownloadItem) that
...@@ -263,6 +268,10 @@ namespace downloads { ...@@ -263,6 +268,10 @@ namespace downloads {
// <code>url</code> matches the given regular expression. // <code>url</code> matches the given regular expression.
DOMString? urlRegex; DOMString? urlRegex;
// Limits results to $(ref:DownloadItem) whose
// <code>finalUrl</code> matches the given regular expression.
DOMString? finalUrlRegex;
// The maximum number of matching $(ref:DownloadItem) returned. Defaults to // The maximum number of matching $(ref:DownloadItem) returned. Defaults to
// 1000. Set to 0 in order to return all matching $(ref:DownloadItem). See // 1000. Set to 0 in order to return all matching $(ref:DownloadItem). See
// $(ref:search) for how to page through results. // $(ref:search) for how to page through results.
...@@ -278,9 +287,14 @@ namespace downloads { ...@@ -278,9 +287,14 @@ namespace downloads {
// The <code>id</code> of the $(ref:DownloadItem) to query. // The <code>id</code> of the $(ref:DownloadItem) to query.
long? id; long? id;
// Absolute URL. // The absolute URL that this download initiated from, before any
// redirects.
DOMString? url; DOMString? url;
// The absolute URL that this download is being made from, after all
// redirects.
DOMString? finalUrl;
// Absolute local path. // Absolute local path.
DOMString? filename; DOMString? filename;
...@@ -346,6 +360,9 @@ namespace downloads { ...@@ -346,6 +360,9 @@ namespace downloads {
// The change in <code>url</code>, if any. // The change in <code>url</code>, if any.
StringDelta? url; StringDelta? url;
// The change in <code>finalUrl</code>, if any.
StringDelta? finalUrl;
// The change in <code>filename</code>, if any. // The change in <code>filename</code>, if any.
StringDelta? filename; StringDelta? filename;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment