Bug 1503760: Changed browser.downloads.search({}) to return 0 byte downloads. r=aswan
authorBen Armstrong <ben.armstrong22@gmail.com>
Mon, 26 Nov 2018 22:54:49 +0000
changeset 508387 e990a032ac3cf6c071a79014d4b412bcd2007af1
parent 508386 dcc5dcceb8661d9c74ba44dc2b2280c3b37cf467
child 508388 fb9b6c3665571b702d087dce1bf9e6e024c92131
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1503760
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1503760: Changed browser.downloads.search({}) to return 0 byte downloads. r=aswan Updated the totalBytesGreater property in browser.downloads.search({}) to default to -1 so files with a byte size of 0 will be returned. Differential Revision: https://phabricator.services.mozilla.com/D12344
toolkit/components/extensions/parent/ext-downloads.js
toolkit/components/extensions/schemas/downloads.json
toolkit/components/extensions/test/xpcshell/data/empty_file_download.txt
toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js
--- a/toolkit/components/extensions/parent/ext-downloads.js
+++ b/toolkit/components/extensions/parent/ext-downloads.js
@@ -261,17 +261,17 @@ const downloadQuery = query => {
     return ExtensionCommon.normalizeTime(arg).getTime();
   }
 
   const startedBefore = normalizeDownloadTime(query.startedBefore, true);
   const startedAfter = normalizeDownloadTime(query.startedAfter, false);
   // const endedBefore = normalizeDownloadTime(query.endedBefore, true);
   // const endedAfter = normalizeDownloadTime(query.endedAfter, false);
 
-  const totalBytesGreater = query.totalBytesGreater || 0;
+  const totalBytesGreater = query.totalBytesGreater;
   const totalBytesLess = query.totalBytesLess != null ? query.totalBytesLess : Number.MAX_VALUE;
 
   // Handle options for which we can have a regular expression and/or
   // an explicit value to match.
   function makeMatch(regex, value, field) {
     if (value == null && regex == null) {
       return input => true;
     }
--- a/toolkit/components/extensions/schemas/downloads.json
+++ b/toolkit/components/extensions/schemas/downloads.json
@@ -252,17 +252,18 @@
           "endedAfter": {
             "description": "Limits results to downloads that ended after the given ms since the epoch.",
             "optional": true,
             "$ref": "DownloadTime"
           },
           "totalBytesGreater": {
             "description": "Limits results to downloads whose totalBytes is greater than the given integer.",
             "optional": true,
-            "type": "number"
+            "type": "number",
+            "default": -1
           },
           "totalBytesLess": {
             "description": "Limits results to downloads whose totalBytes is less than the given integer.",
             "optional": true,
             "type": "number"
           },
           "filenameRegex": {
             "description": "Limits results to <a href='#type-DownloadItem'>DownloadItems</a> whose <code>filename</code> matches the given regular expression.",
new file mode 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js
@@ -9,16 +9,19 @@ server.registerDirectory("/data/", do_ge
 
 const BASE = `http://localhost:${server.identity.primaryPort}/data`;
 const TXT_FILE = "file_download.txt";
 const TXT_URL = BASE + "/" + TXT_FILE;
 const TXT_LEN = 46;
 const HTML_FILE = "file_download.html";
 const HTML_URL = BASE + "/" + HTML_FILE;
 const HTML_LEN = 117;
+const EMPTY_FILE = "empty_file_download.txt";
+const EMPTY_URL = BASE + "/" + EMPTY_FILE;
+const EMPTY_LEN = 0;
 const BIG_LEN = 1000; // something bigger both TXT_LEN and HTML_LEN
 
 function backgroundScript() {
   let complete = new Map();
 
   function waitForComplete(id) {
     if (complete.has(id)) {
       return complete.get(id).promise;
@@ -137,16 +140,20 @@ add_task(async function test_search() {
   equal(msg.status, "success", "download() succeeded");
   downloadIds.txt1 = msg.id;
 
   const TXT_FILE2 = "NewFile.txt";
   msg = await download({url: TXT_URL, filename: TXT_FILE2});
   equal(msg.status, "success", "download() succeeded");
   downloadIds.txt2 = msg.id;
 
+  msg = await download({url: EMPTY_URL});
+  equal(msg.status, "success", "download() succeeded");
+  downloadIds.txt3 = msg.id;
+
   const time2 = new Date();
 
   msg = await download({url: HTML_URL});
   equal(msg.status, "success", "download() succeeded");
   downloadIds.html1 = msg.id;
 
   const HTML_FILE2 = "renamed.html";
   msg = await download({url: HTML_URL, filename: HTML_FILE2});
@@ -183,16 +190,27 @@ add_task(async function test_search() {
     mime: "text/plain",
     state: "complete",
     bytesReceived: TXT_LEN,
     totalBytes: TXT_LEN,
     fileSize: TXT_LEN,
     exists: true,
   });
 
+  await checkDownloadItem(downloadIds.txt3, {
+    url: EMPTY_URL,
+    filename: downloadPath(EMPTY_FILE),
+    mime: "text/plain",
+    state: "complete",
+    bytesReceived: EMPTY_LEN,
+    totalBytes: EMPTY_LEN,
+    fileSize: EMPTY_LEN,
+    exists: true,
+  });
+
   await checkDownloadItem(downloadIds.html1, {
     url: HTML_URL,
     filename: downloadPath(HTML_FILE),
     mime: "text/html",
     state: "complete",
     bytesReceived: HTML_LEN,
     totalBytes: HTML_LEN,
     fileSize: HTML_LEN,
@@ -257,17 +275,17 @@ add_task(async function test_search() {
 
   // Check that compatible filename+regexp works
   await checkSearch({filename: downloadPath(HTML_FILE), filenameRegex: HTML_REGEX}, ["html1"], "compatible filename+filename regex");
 
   // Check that incompatible filename+regexp works
   await checkSearch({filename: downloadPath(TXT_FILE), filenameRegex: HTML_REGEX}, [], "incompatible filename+filename regex");
 
   // Check that simple positive search terms work.
-  await checkSearch({query: ["file_download"]}, ["txt1", "txt2", "html1", "html2"],
+  await checkSearch({query: ["file_download"]}, ["txt1", "txt2", "txt3", "html1", "html2"],
                     "term file_download");
   await checkSearch({query: ["NewFile"]}, ["txt2"], "term NewFile");
 
   // Check that positive search terms work case-insensitive.
   await checkSearch({query: ["nEwfILe"]}, ["txt2"], "term nEwfiLe");
 
   // Check that negative search terms work.
   await checkSearch({query: ["-txt"]}, ["html1", "html2"], "term -txt");
@@ -299,49 +317,52 @@ add_task(async function test_search() {
 
     // Check as ISO string
     newquery[field] = date.toISOString();
     await checkSearch(newquery, expected, `${description} as iso string`);
   }
 
   // Check startedBefore
   await checkSearchWithDate({startedBefore: time1}, [], "before time1");
-  await checkSearchWithDate({startedBefore: time2}, ["txt1", "txt2"], "before time2");
-  await checkSearchWithDate({startedBefore: time3}, ["txt1", "txt2", "html1", "html2"], "before time3");
+  await checkSearchWithDate({startedBefore: time2}, ["txt1", "txt2", "txt3"], "before time2");
+  await checkSearchWithDate({startedBefore: time3}, ["txt1", "txt2", "txt3", "html1", "html2"], "before time3");
 
   // Check startedAfter
-  await checkSearchWithDate({startedAfter: time1}, ["txt1", "txt2", "html1", "html2"], "after time1");
+  await checkSearchWithDate({startedAfter: time1}, ["txt1", "txt2", "txt3", "html1", "html2"], "after time1");
   await checkSearchWithDate({startedAfter: time2}, ["html1", "html2"], "after time2");
   await checkSearchWithDate({startedAfter: time3}, [], "after time3");
 
   // Check simple search on totalBytes
   await checkSearch({totalBytes: TXT_LEN}, ["txt1", "txt2"], "totalBytes");
   await checkSearch({totalBytes: HTML_LEN}, ["html1", "html2"], "totalBytes");
 
   // Check simple test on totalBytes{Greater,Less}
   // (NB: TXT_LEN < HTML_LEN < BIG_LEN)
   await checkSearch({totalBytesGreater: 0}, ["txt1", "txt2", "html1", "html2"], "totalBytesGreater than 0");
   await checkSearch({totalBytesGreater: TXT_LEN}, ["html1", "html2"], `totalBytesGreater than ${TXT_LEN}`);
   await checkSearch({totalBytesGreater: HTML_LEN}, [], `totalBytesGreater than ${HTML_LEN}`);
-  await checkSearch({totalBytesLess: TXT_LEN}, [], `totalBytesLess than ${TXT_LEN}`);
-  await checkSearch({totalBytesLess: HTML_LEN}, ["txt1", "txt2"], `totalBytesLess than ${HTML_LEN}`);
-  await checkSearch({totalBytesLess: BIG_LEN}, ["txt1", "txt2", "html1", "html2"], `totalBytesLess than ${BIG_LEN}`);
+  await checkSearch({totalBytesLess: TXT_LEN}, ["txt3"], `totalBytesLess than ${TXT_LEN}`);
+  await checkSearch({totalBytesLess: HTML_LEN}, ["txt1", "txt2", "txt3"], `totalBytesLess than ${HTML_LEN}`);
+  await checkSearch({totalBytesLess: BIG_LEN}, ["txt1", "txt2", "txt3", "html1", "html2"], `totalBytesLess than ${BIG_LEN}`);
+
+  // Bug 1503760 check if 0 byte files with no search query are returned.
+  await checkSearch({}, ["txt1", "txt2", "txt3", "html1", "html2"], "totalBytesGreater than -1");
 
   // Check good combinations of totalBytes*.
   await checkSearch({totalBytes: HTML_LEN, totalBytesGreater: TXT_LEN}, ["html1", "html2"], "totalBytes and totalBytesGreater");
   await checkSearch({totalBytes: TXT_LEN, totalBytesLess: HTML_LEN}, ["txt1", "txt2"], "totalBytes and totalBytesGreater");
   await checkSearch({totalBytes: HTML_LEN, totalBytesLess: BIG_LEN, totalBytesGreater: 0}, ["html1", "html2"], "totalBytes and totalBytesLess and totalBytesGreater");
 
   // Check bad combination of totalBytes*.
   await checkSearch({totalBytesLess: TXT_LEN, totalBytesGreater: HTML_LEN}, [], "bad totalBytesLess, totalBytesGreater combination");
   await checkSearch({totalBytes: TXT_LEN, totalBytesGreater: HTML_LEN}, [], "bad totalBytes, totalBytesGreater combination");
   await checkSearch({totalBytes: HTML_LEN, totalBytesLess: TXT_LEN}, [], "bad totalBytes, totalBytesLess combination");
 
   // Check mime.
-  await checkSearch({mime: "text/plain"}, ["txt1", "txt2"], "mime text/plain");
+  await checkSearch({mime: "text/plain"}, ["txt1", "txt2", "txt3"], "mime text/plain");
   await checkSearch({mime: "text/html"}, ["html1", "html2"], "mime text/htmlplain");
   await checkSearch({mime: "video/webm"}, [], "mime video/webm");
 
   // Check fileSize.
   await checkSearch({fileSize: TXT_LEN}, ["txt1", "txt2"], "fileSize");
   await checkSearch({fileSize: HTML_LEN}, ["html1", "html2"], "fileSize");
 
   // Fields like bytesReceived, paused, state, exists are meaningful
@@ -366,25 +387,26 @@ add_task(async function test_search() {
     totalBytes: TXT_LEN,
     totalBytesGreater: 0,
     totalBytesLess: BIG_LEN,
     mime: "text/plain",
     fileSize: TXT_LEN,
   }, ["txt1"], "many properties");
 
   // Check simple orderBy (forward and backward).
-  await checkSearch({orderBy: ["startTime"]}, ["txt1", "txt2", "html1", "html2"], "orderBy startTime", true);
-  await checkSearch({orderBy: ["-startTime"]}, ["html2", "html1", "txt2", "txt1"], "orderBy -startTime", true);
+  await checkSearch({orderBy: ["startTime"]}, ["txt1", "txt2", "txt3", "html1", "html2"], "orderBy startTime", true);
+  await checkSearch({orderBy: ["-startTime"]}, ["html2", "html1", "txt3", "txt2", "txt1"], "orderBy -startTime", true);
 
   // Check orderBy with multiple fields.
   // NB: TXT_URL and HTML_URL differ only in extension and .html precedes .txt
-  await checkSearch({orderBy: ["url", "-startTime"]}, ["html2", "html1", "txt2", "txt1"], "orderBy with multiple fields", true);
+  // EMPTY_URL begins with e which precedes f
+  await checkSearch({orderBy: ["url", "-startTime"]}, ["txt3", "html2", "html1", "txt2", "txt1"], "orderBy with multiple fields", true);
 
   // Check orderBy with limit.
-  await checkSearch({orderBy: ["url"], limit: 1}, ["html1"], "orderBy with limit", true);
+  await checkSearch({orderBy: ["url"], limit: 1}, ["txt3"], "orderBy with limit", true);
 
   // Check bad arguments.
   async function checkBadSearch(query, pattern, description) {
     let item = await search(query);
     equal(item.status, "error", "search() failed");
     ok(pattern.test(item.errmsg), `error message for ${description} was correct (${item.errmsg}).`);
   }