Backed out changeset 63132b94b6a3 (bug 1245603) for mochitest-chrome failures in test_chrome_ext_downloads_search.html
authorWes Kocher <wkocher@mozilla.com>
Wed, 02 Mar 2016 12:42:37 -0800
changeset 322770 5ea9a54a24d60dc63df47c4f7f5231b66d8835c6
parent 322769 c36859eaec38c5f0aeb886b97be0950f7a0dd259
child 322771 7ccac48f64f2d9897d630a193e7becebdd87eaf7
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1245603
milestone47.0a1
backs out63132b94b6a39f017e9952486e01b1041b5a2d9f
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
Backed out changeset 63132b94b6a3 (bug 1245603) for mochitest-chrome failures in test_chrome_ext_downloads_search.html MozReview-Commit-ID: D1tlLwaDs6A
toolkit/components/extensions/ext-downloads.js
toolkit/components/extensions/schemas/downloads.json
toolkit/components/extensions/test/mochitest/chrome.ini
toolkit/components/extensions/test/mochitest/file_download.html
toolkit/components/extensions/test/mochitest/mochitest.ini
toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_search.html
--- a/toolkit/components/extensions/ext-downloads.js
+++ b/toolkit/components/extensions/ext-downloads.js
@@ -15,272 +15,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 const {
   ignoreEvent,
 } = ExtensionUtils;
 
-const DOWNLOAD_ITEM_FIELDS = ["id", "url", "referrer", "filename", "incognito",
-                              "danger", "mime", "startTime", "endTime",
-                              "estimatedEndTime", "state", "canResume",
-                              "error", "bytesReceived", "totalBytes",
-                              "fileSize", "exists",
-                              "byExtensionId", "byExtensionName"];
-
-class DownloadItem {
-  constructor(id, download, extension) {
-    this.id = id;
-    this.download = download;
-    this.extension = extension;
-  }
-
-  get url() { return this.download.source.url; }
-  get referrer() { return this.download.source.referrer; }
-  get filename() { return this.download.target.path; }
-  get incognito() { return this.download.source.isPrivate; }
-  get danger() { return "safe"; } // TODO
-  get mime() { return this.download.contentType; }
-  get startTime() { return this.download.startTime; }
-  get endTime() { return null; } // TODO
-  get estimatedEndTime() { return null; } // TODO
-  get state() {
-    if (this.download.succeeded) {
-      return "complete";
-    }
-    if (this.download.stopped) {
-      return "interrupted";
-    }
-    return "in_progress";
-  }
-  get canResume() {
-    return this.download.stopped && this.download.hasPartialData;
-  }
-  get error() {
-    if (!this.download.stopped || this.download.succeeded) {
-      return null;
-    }
-    // TODO store this instead of calculating it
-
-    if (this.download.error) {
-      if (this.download.error.becauseSourceFailed) {
-        return "NETWORK_FAILED"; // TODO
-      }
-      if (this.download.error.becauseTargetFailed) {
-        return "FILE_FAILED"; // TODO
-      }
-      return "CRASH";
-    }
-    return "USER_CANCELED";
-  }
-  get bytesReceived() {
-    return this.download.currentBytes;
-  }
-  get totalBytes() {
-    return this.download.hasProgress ? this.download.totalBytes : -1;
-  }
-  get fileSize() {
-    // todo: this is supposed to be post-compression
-    return this.download.succeeded ? this.download.target.size : -1;
-  }
-  get exists() { return this.download.target.exists; }
-  get byExtensionId() { return this.extension.id; }
-  get byExtensionName() { return this.extension.name; }
-
-  /**
-   * Create a cloneable version of this object by pulling all the
-   * fields into simple properties (instead of getters).
-   *
-   * @returns {object} A DownloadItem with flat properties,
-   *                   suitable for cloning.
-   */
-  serialize() {
-    let obj = {};
-    for (let field of DOWNLOAD_ITEM_FIELDS) {
-      obj[field] = this[field];
-    }
-    if (obj.startTime) {
-      obj.startTime = obj.startTime.toISOString();
-    }
-    return obj;
-  }
-}
-
-
-// DownloadMap maps back and forth betwen the numeric identifiers used in
-// the downloads WebExtension API and a Download object from the Downloads jsm.
-// todo: make id and extension info persistent (bug 1247794)
-const DownloadMap = {
-  currentId: 0,
-  loadPromise: null,
-
-  // Maps numeric id -> DownloadItem
-  byId: new Map(),
-
-  // Maps Download object -> DownloadItem
-  byDownload: new WeakMap(),
-
-  lazyInit() {
-    return Downloads.getList(Downloads.ALL).then(list => {
-      return list.getAll().then(downloads => {
-        downloads.forEach(download => {
-          this.newFromDownload(download, null);
-        });
-        let self = this;
-        return list.addView({
-          onDownloadAdded(download) {
-            self.newFromDownload(download, null);
-          },
-
-          onDownloadRemoved(download) {
-            const item = self.byDownload.get(download);
-            if (item != null) {
-              self.byDownload.delete(download);
-              self.byId.delete(item.id);
-            }
-          },
-        });
-      });
-    });
-  },
-
-  getAll() {
-    if (this.loadPromise == null) {
-      this.loadPromise = this.lazyInit();
-    }
-    return this.loadPromise.then(() => this.byId.values());
-  },
-
-  fromId(id) {
-    const download = this.byId.get(id);
-    if (!download) {
-      throw new Error(`Invalid download id ${id}`);
-    }
-    return download;
-  },
-
-  newFromDownload(download, extension) {
-    if (this.byDownload.has(download)) {
-      return this.byDownload.get(download);
-    }
-
-    const id = ++this.currentId;
-    let item = new DownloadItem(id, download, extension);
-    this.byId.set(id, item);
-    this.byDownload.set(download, item);
-    return item;
-  },
-};
-
-// Create a callable function that filters a DownloadItem based on a
-// query object of the type passed to search() or erase().
-function downloadQuery(query) {
-  let queryTerms = [];
-  let queryNegativeTerms = [];
-  if (query.query != null) {
-    for (let term of query.query) {
-      if (term[0] == "-") {
-        queryNegativeTerms.push(term.slice(1).toLowerCase());
-      } else {
-        queryTerms.push(term.toLowerCase());
-      }
-    }
-  }
-
-  function normalizeTime(arg, before) {
-    if (arg == null) {
-      return before ? Number.MAX_VALUE : 0;
-    }
-    return parseInt(arg, 10);
-  }
-
-  const startedBefore = normalizeTime(query.startedBefore, true);
-  const startedAfter = normalizeTime(query.startedAfter, false);
-  // const endedBefore = normalizeTime(query.endedBefore, true);
-  // const endedAfter = normalizeTime(query.endedAfter, false);
-
-  const totalBytesGreater = query.totalBytesGreater || 0;
-  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;
-    }
-
-    let re;
-    try {
-      re = new RegExp(regex || "", "i");
-    } catch (err) {
-      throw new Error(`Invalid ${field}Regex: ${err.message}`);
-    }
-    if (value == null) {
-      return input => re.test(input);
-    }
-
-    value = value.toLowerCase();
-    if (re.test(value)) {
-      return input => (value == input);
-    } else {
-      return input => false;
-    }
-  }
-
-  const matchFilename = makeMatch(query.filenameRegex, query.filename, "filename");
-  const matchUrl = makeMatch(query.urlRegex, query.url, "url");
-
-  return function(item) {
-    const url = item.url.toLowerCase();
-    const filename = item.filename.toLowerCase();
-
-    if (!queryTerms.every(term => url.includes(term) || filename.includes(term))) {
-      return false;
-    }
-
-    if (queryNegativeTerms.some(term => url.includes(term) || filename.includes(term))) {
-      return false;
-    }
-
-    if (!matchFilename(filename) || !matchUrl(url)) {
-      return false;
-    }
-
-    if (!item.startTime) {
-      if (query.startedBefore != null || query.startedAfter != null) {
-        return false;
-      }
-    } else if (item.startTime > startedBefore || item.startTime < startedAfter) {
-      return false;
-    }
-
-    // todo endedBefore, endedAfter
-
-    if (item.totalBytes == -1) {
-      if (query.totalBytesGreater != null || query.totalBytesLess != null) {
-        return false;
-      }
-    } else if (item.totalBytes <= totalBytesGreater || item.totalBytes >= totalBytesLess) {
-      return false;
-    }
-
-    // todo: include danger, paused, error
-    const SIMPLE_ITEMS = ["id", "mime", "startTime", "endTime", "state",
-                          "bytesReceived", "totalBytes", "fileSize", "exists"];
-    for (let field of SIMPLE_ITEMS) {
-      if (query[field] != null && item[field] != query[field]) {
-        return false;
-      }
-    }
-
-    return true;
-  };
-}
+let currentId = 0;
 
 extensions.registerSchemaAPI("downloads", "downloads", (extension, context) => {
   return {
     downloads: {
       download(options) {
         if (options.filename != null) {
           if (options.filename.length == 0) {
             return Promise.reject({message: "filename must not be empty"});
@@ -344,74 +89,22 @@ extensions.registerSchemaAPI("downloads"
             return Downloads.getList(Downloads.ALL);
           }).then(list => {
             list.add(download);
 
             // This is necessary to make pause/resume work.
             download.tryToKeepPartialData = true;
             download.start();
 
-            const item = DownloadMap.newFromDownload(download, extension);
-            return item.id;
+            // Without other chrome.downloads methods, we can't actually
+            // do anything with the id so just return a dummy value for now.
+            return currentId++;
           });
       },
 
-      search(query) {
-        let matchFn;
-        try {
-          matchFn = downloadQuery(query);
-        } catch (err) {
-          return Promise.reject({message: err.message});
-        }
-
-        let compareFn;
-        if (query.orderBy != null) {
-          const fields = query.orderBy.map(field => field[0] == "-"
-                                           ? {reverse: true, name: field.slice(1)}
-                                           : {reverse: false, name: field});
-
-          for (let field of fields) {
-            if (!DOWNLOAD_ITEM_FIELDS.includes(field.name)) {
-              return Promise.reject({message: `Invalid orderBy field ${field.name}`});
-            }
-          }
-
-          compareFn = (dl1, dl2) => {
-            for (let field of fields) {
-              const val1 = dl1[field.name];
-              const val2 = dl2[field.name];
-
-              if (val1 < val2) {
-                return field.reverse ? 1 : -1;
-              } else if (val1 > val2) {
-                return field.reverse ? -1 : 1;
-              }
-            }
-            return 0;
-          };
-        }
-
-        return DownloadMap.getAll().then(downloads => {
-          if (compareFn) {
-            downloads = Array.from(downloads);
-            downloads.sort(compareFn);
-          }
-          let results = [];
-          for (let download of downloads) {
-            if (query.limit && results.length >= query.limit) {
-              break;
-            }
-            if (matchFn(download)) {
-              results.push(download.serialize());
-            }
-          }
-          return results;
-        });
-      },
-
       // When we do open(), check for additional downloads.open permission.
       // i.e.:
       // open(downloadId) {
       //   if (!extension.hasPermission("downloads.open")) {
       //     throw new context.cloneScope.Error("Permission denied because 'downloads.open' permission is missing.");
       //   }
       //   ...
       // }
--- a/toolkit/components/extensions/schemas/downloads.json
+++ b/toolkit/components/extensions/schemas/downloads.json
@@ -290,52 +290,48 @@
               }
             ]
           }
         ]
       },
       {
         "name": "search",
         "type": "function",
-        "async": "callback",
+        "unsupported": true,
         "description": "Find <a href='#type-DownloadItem'>DownloadItems</a>. Set <code>query</code> to the empty object to get all <a href='#type-DownloadItem'>DownloadItems</a>. To get a specific <a href='#type-DownloadItem'>DownloadItem</a>, set only the <code>id</code> field.",
         "parameters": [
           {
             "name": "query",
             "type": "object",
             "properties": {
               "query": {
                 "description": "This array of search terms limits results to <a href='#type-DownloadItem'>DownloadItems</a> whose <code>filename</code> or <code>url</code> contain all of the search terms that do not begin with a dash '-' and none of the search terms that do begin with a dash.",
                 "optional": true,
                 "type": "array",
                 "items": { "type": "string" }
               },
               "startedBefore": {
                 "description": "Limits results to downloads that started before the given ms since the epoch.",
                 "optional": true,
-                "type": "string",
-                "pattern": "^[1-9]\\d*$"
+                "type": "string"
               },
               "startedAfter": {
                 "description": "Limits results to downloads that started after the given ms since the epoch.",
                 "optional": true,
-                "type": "string",
-                "pattern": "^[1-9]\\d*$"
+                "type": "string"
               },
               "endedBefore": {
                 "description": "Limits results to downloads that ended before the given ms since the epoch.",
                 "optional": true,
-                "type": "string",
-                "pattern": "^[1-9]\\d*$"
+                "type": "string"
               },
               "endedAfter": {
                 "description": "Limits results to downloads that ended after the given ms since the epoch.",
                 "optional": true,
-                "type": "string",
-                "pattern": "^[1-9]\\d*$"
+                "type": "string"
               },
               "totalBytesGreater": {
                 "description": "Limits results to downloads whose totalBytes is greater than the given integer.",
                 "optional": true,
                 "type": "number"
               },
               "totalBytesLess": {
                 "description": "Limits results to downloads whose totalBytes is less than the given integer.",
--- a/toolkit/components/extensions/test/mochitest/chrome.ini
+++ b/toolkit/components/extensions/test/mochitest/chrome.ini
@@ -1,8 +1,6 @@
 [DEFAULT]
 skip-if = os == 'android'
 support-files =
-  file_download.html
   file_download.txt
 
 [test_chrome_ext_downloads_download.html]
-[test_chrome_ext_downloads_search.html]
deleted file mode 100644
--- a/toolkit/components/extensions/test/mochitest/file_download.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE HTML>
-
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body>
-
-<div>Download HTML File</div>
-
-</body>
-</html>
--- a/toolkit/components/extensions/test/mochitest/mochitest.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest.ini
@@ -17,17 +17,16 @@ support-files =
   file_script_bad.js
   file_script_redirect.js
   file_script_xhr.js
   file_sample.html
   redirection.sjs
   file_privilege_escalation.html
   file_ext_test_api_injection.js
   file_permission_xhr.html
-  file_download.txt
 
 [test_ext_simple.html]
 [test_ext_schema.html]
 skip-if = e10s # Uses a console montitor. Actual code does not depend on e10s.
 [test_ext_geturl.html]
 [test_ext_contentscript.html]
 skip-if = buildapp == 'b2g' # runat != document_idle is not supported.
 [test_ext_contentscript_create_iframe.html]
deleted file mode 100644
--- a/toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_search.html
+++ /dev/null
@@ -1,373 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>WebExtension test</title>
-  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
-  <script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
-  <script type="text/javascript" src="head.js"></script>
-  <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
-</head>
-<body>
-
-<script type="text/javascript">
-"use strict";
-
-const {
-  interfaces: Ci,
-  utils: Cu,
-} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-
-const BASE = "http://mochi.test:8888/chrome/toolkit/components/extensions/test/mochitest";
-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 BIG_LEN = 1000;  // something bigger both TXT_LEN and HTML_LEN
-
-function backgroundScript() {
-  browser.test.onMessage.addListener(function(msg) {
-    // extension functions throw on bad arguments, we can remove the extra
-    // promise when bug 1250223 is fixed.
-    if (msg == "download.request") {
-      Promise.resolve().then(() => browser.downloads.download(arguments[1]))
-                       .then(id => {
-                         browser.test.sendMessage("download.done", {status: "success", id});
-                       })
-                       .catch(error => {
-                         browser.test.sendMessage("download.done", {status: "error", errmsg: error.message});
-                       });
-    } else if (msg == "search.request") {
-      Promise.resolve().then(() => browser.downloads.search(arguments[1]))
-                       .then(downloads => {
-                         browser.test.sendMessage("search.done", {status: "success", downloads});
-                       })
-                       .catch(error => {
-                         browser.test.sendMessage("search.done", {status: "error", errmsg: error.message});
-                       });
-    }
-  });
-
-  browser.test.sendMessage("ready");
-}
-
-add_task(function* test_search() {
-  const nsIFile = Ci.nsIFile;
-  let downloadDir = FileUtils.getDir("TmpD", ["downloads"]);
-  downloadDir.createUnique(nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
-  info(`downloadDir ${downloadDir.path}`);
-
-  function downloadPath(filename) {
-    let path = downloadDir.clone();
-    path.append(filename);
-    return path.path;
-  }
-
-  Services.prefs.setIntPref("browser.download.folderList", 2);
-  Services.prefs.setComplexValue("browser.download.dir", nsIFile, downloadDir);
-
-  SimpleTest.registerCleanupFunction(() => {
-    Services.prefs.clearUserPref("browser.download.folderList");
-    Services.prefs.clearUserPref("browser.download.dir");
-    downloadDir.remove(true);
-  });
-
-  let extension = ExtensionTestUtils.loadExtension({
-    background: `(${backgroundScript})()`,
-    manifest: {
-      permissions: ["downloads"],
-    },
-  });
-
-  function download(options) {
-    extension.sendMessage("download.request", options);
-    return extension.awaitMessage("download.done");
-  }
-
-  function search(query) {
-    extension.sendMessage("search.request", query);
-    return extension.awaitMessage("search.done");
-  }
-
-  yield extension.startup();
-  yield extension.awaitMessage("ready");
-  info("extension started");
-
-  // Do some downloads...
-  const time1 = new Date();
-
-  let downloadIds = {};
-  let msg = yield download({url: TXT_URL});
-  is(msg.status, "success", "download() succeeded");
-  downloadIds.txt1 = msg.id;
-
-  const TXT_FILE2 = "NewFile.txt";
-  msg = yield download({url: TXT_URL, filename: TXT_FILE2});
-  is(msg.status, "success", "download() succeeded");
-  downloadIds.txt2 = msg.id;
-
-  const time2 = new Date();
-
-  msg = yield download({url: HTML_URL});
-  is(msg.status, "success", "download() succeeded");
-  downloadIds.html1 = msg.id;
-
-  const HTML_FILE2 = "renamed.html";
-  msg = yield download({url: HTML_URL, filename: HTML_FILE2});
-  is(msg.status, "success", "download() succeeded");
-  downloadIds.html2 = msg.id;
-
-  const time3 = new Date();
-
-  // Yuck, until we have onChanged, poll for downloads to finish.
-  // Since there are just 4 small downloads, this shouldn't be a big deal.
-  for (let attempt = 0; attempt < 5; attempt++) {
-    let msg = yield search({});
-    if (msg.status == "success" && msg.downloads.length == 4
-        && msg.downloads.every(download => download.state == "complete")) {
-      info("4 downloads complete, proceeding");
-      break;
-    }
-    info("downloads aren't finished, checking again");
-  }
-
-  // Search for each individual download and check
-  // the corresponding DownloadItem.
-  function* checkDownloadItem(id, expect) {
-    let msg = yield search({id});
-    is(msg.status, "success", "search() succeeded");
-    is(msg.downloads.length, 1, "search() found exactly 1 download");
-
-    Object.keys(expect).forEach(function(field) {
-      is(msg.downloads[0][field], expect[field], `DownloadItem.${field} is correct"`);
-    });
-  }
-  yield checkDownloadItem(downloadIds.txt1, {
-    url: TXT_URL,
-    filename: downloadPath(TXT_FILE),
-    mime: "text/plain",
-    state: "complete",
-    bytesReceived: TXT_LEN,
-    totalBytes: TXT_LEN,
-    fileSize: TXT_LEN,
-    exists: true,
-  });
-
-  yield checkDownloadItem(downloadIds.txt2, {
-    url: TXT_URL,
-    filename: downloadPath(TXT_FILE2),
-    mime: "text/plain",
-    state: "complete",
-    bytesReceived: TXT_LEN,
-    totalBytes: TXT_LEN,
-    fileSize: TXT_LEN,
-    exists: true,
-  });
-
-  yield checkDownloadItem(downloadIds.html1, {
-    url: HTML_URL,
-    filename: downloadPath(HTML_FILE),
-    mime: "text/html",
-    state: "complete",
-    bytesReceived: HTML_LEN,
-    totalBytes: HTML_LEN,
-    fileSize: HTML_LEN,
-    exists: true,
-  });
-
-  yield checkDownloadItem(downloadIds.html2, {
-    url: HTML_URL,
-    filename: downloadPath(HTML_FILE2),
-    mime: "text/html",
-    state: "complete",
-    bytesReceived: HTML_LEN,
-    totalBytes: HTML_LEN,
-    fileSize: HTML_LEN,
-    exists: true,
-  });
-
-  function* checkSearch(query, expected, description, exact) {
-    let msg = yield search(query);
-    is(msg.status, "success", "search() succeeded");
-    is(msg.downloads.length, expected.length, `search() for ${description} found exactly ${expected.length} downloads`);
-
-    let receivedIds = msg.downloads.map(item => item.id);
-    if (exact) {
-      receivedIds.forEach((id, idx) => {
-        is(id, downloadIds[expected[idx]], `search() for ${description} returned ${expected[idx]} in position ${idx}`);
-      });
-    } else {
-      Object.keys(downloadIds).forEach(key => {
-        const id = downloadIds[key];
-        const thisExpected = expected.includes(key);
-        is(receivedIds.includes(id), thisExpected,
-           `search() for ${description} ${thisExpected ? "includes" : "does not include"} ${key}`);
-      });
-    }
-  }
-
-  // Check that search with an invalid id returns nothing.
-  // NB: for now ids are not persistent and we start numbering them at 1
-  //     so a sufficiently large number will be unused.
-  const INVALID_ID = 1000;
-  yield checkSearch({id: INVALID_ID}, [], "invalid id");
-
-  // Check that search on url works.
-  yield checkSearch({url: TXT_URL}, ["txt1", "txt2"], "url");
-
-  // Check that regexp on url works.
-  const HTML_REGEX = "[downlad]{8}\.html+$";
-  yield checkSearch({urlRegex: HTML_REGEX}, ["html1", "html2"], "url regexp");
-
-  // Check that compatible url+regexp works
-  yield checkSearch({url: HTML_URL, urlRegex: HTML_REGEX}, ["html1", "html2"], "compatible url+urlRegex");
-
-  // Check that incompatible url+regexp works
-  yield checkSearch({url: TXT_URL, urlRegex: HTML_REGEX}, [], "incompatible url+urlRegex");
-
-  // Check that search on filename works.
-  yield checkSearch({filename: downloadPath(TXT_FILE)}, ["txt1"], "filename");
-
-  // Check that regexp on filename works.
-  yield checkSearch({filenameRegex: HTML_REGEX}, ["html1"], "filename regex");
-
-  // Check that compatible filename+regexp works
-  yield checkSearch({filename: downloadPath(HTML_FILE), filenameRegex: HTML_REGEX}, ["html1"], "compatible filename+filename regex");
-
-  // Check that incompatible filename+regexp works
-  yield checkSearch({filename: downloadPath(TXT_FILE), filenameRegex: HTML_REGEX}, [], "incompatible filename+filename regex");
-
-  // Check that simple positive search terms work.
-  yield checkSearch({query: ["file_download"]}, ["txt1", "txt2", "html1", "html2"],
-                    "term file_download");
-  yield checkSearch({query: ["NewFile"]}, ["txt2"], "term NewFile");
-
-  // Check that positive search terms work case-insensitive.
-  yield checkSearch({query: ["nEwfILe"]}, ["txt2"], "term nEwfiLe");
-
-  // Check that negative search terms work.
-  yield checkSearch({query: ["-txt"]}, ["html1", "html2"], "term -txt");
-
-  // Check that positive and negative search terms together work.
-  yield checkSearch({query: ["html", "-renamed"]}, ["html1"], "postive and negative terms");
-
-  // Check that startedBefore works with stringified milliseconds.
-  yield checkSearch({startedBefore: time1.valueOf().toString()}, [], "before time1");
-  yield checkSearch({startedBefore: time2.valueOf().toString()}, ["txt1", "txt2"], "before time2");
-  yield checkSearch({startedBefore: time3.valueOf().toString()}, ["txt1", "txt2", "html1", "html2"], "before time3");
-
-  // Check that startedBefore works with iso string.
-  // enable with fix for bug 1251766
-  // yield checkSearch({startedBefore: time1.toISOString()}, [], "before time1");
-  // yield checkSearch({startedBefore: time2.toISOString()}, ["txt1", "txt2"], "before time2");
-  // yield checkSearch({startedBefore: time3.toISOString()}, ["txt1", "txt2", "html1", "html2"], "before time3");
-
-  // Check that startedAfter works with stringified milliseconds.
-  yield checkSearch({startedAfter: time1.valueOf().toString()}, ["txt1", "txt2", "html1", "html2"], "after time1");
-  yield checkSearch({startedAfter: time2.valueOf().toString()}, ["html1", "html2"], "after time2");
-  yield checkSearch({startedAfter: time3.valueOf().toString()}, [], "after time3");
-
-  // Check that startedAfter works with iso string.
-  // enable with fix for bug 1251766
-  // yield checkSearch({startedAfter: time1.toISOString()}, ["txt1", "txt2", "html1", "html2"], "after time1");
-  // yield checkSearch({startedAfter: time2.toISOString()}, ["html1", "html2"], "after time2");
-  // yield checkSearch({startedAfter: time3.toISOString()}, [], "after time3");
-
-  // Check simple search on totalBytes
-  yield checkSearch({totalBytes: TXT_LEN}, ["txt1", "txt2"], "totalBytes");
-  yield checkSearch({totalBytes: HTML_LEN}, ["html1", "html2"], "totalBytes");
-
-  // Check simple test on totalBytes{Greater,Less}
-  // (NB: TXT_LEN < HTML_LEN < BIG_LEN)
-  yield checkSearch({totalBytesGreater: 0}, ["txt1", "txt2", "html1", "html2"], "totalBytesGreater than 0");
-  yield checkSearch({totalBytesGreater: TXT_LEN}, ["html1", "html2"], `totalBytesGreater than ${TXT_LEN}`);
-  yield checkSearch({totalBytesGreater: HTML_LEN}, [], `totalBytesGreater than ${HTML_LEN}`);
-  yield checkSearch({totalBytesLess: TXT_LEN}, [], `totalBytesLess than ${TXT_LEN}`);
-  yield checkSearch({totalBytesLess: HTML_LEN}, ["txt1", "txt2"], `totalBytesLess than ${HTML_LEN}`);
-  yield checkSearch({totalBytesLess: BIG_LEN}, ["txt1", "txt2", "html1", "html2"], `totalBytesLess than ${BIG_LEN}`);
-
-  // Check good combinations of totalBytes*.
-  yield checkSearch({totalBytes: HTML_LEN, totalBytesGreater: TXT_LEN}, ["html1", "html2"], "totalBytes and totalBytesGreater");
-  yield checkSearch({totalBytes: TXT_LEN, totalBytesLess: HTML_LEN}, ["txt1", "txt2"], "totalBytes and totalBytesGreater");
-  yield checkSearch({totalBytes: HTML_LEN, totalBytesLess: BIG_LEN, totalBytesGreater: 0}, ["html1", "html2"], "totalBytes and totalBytesLess and totalBytesGreater");
-
-  // Check bad combination of totalBytes*.
-  yield checkSearch({totalBytesLess: TXT_LEN, totalBytesGreater: HTML_LEN}, [], "bad totalBytesLess, totalBytesGreater combination");
-  yield checkSearch({totalBytes: TXT_LEN, totalBytesGreater: HTML_LEN}, [], "bad totalBytes, totalBytesGreater combination");
-  yield checkSearch({totalBytes: HTML_LEN, totalBytesLess: TXT_LEN}, [], "bad totalBytes, totalBytesLess combination");
-
-  // Check mime.
-  yield checkSearch({mime: "text/plain"}, ["txt1", "txt2"], "mime text/plain");
-  yield checkSearch({mime: "text/html"}, ["html1", "html2"], "mime text/htmlplain");
-  yield checkSearch({mime: "video/webm"}, [], "mime video/webm");
-
-  // Check fileSize.
-  yield checkSearch({fileSize: TXT_LEN}, ["txt1", "txt2"], "fileSize");
-  yield checkSearch({fileSize: HTML_LEN}, ["html1", "html2"], "fileSize");
-
-  // Fields like bytesReceived, paused, state, exists are meaningful
-  // for downloads that are in progress but have not yet completed.
-  // todo: add tests for these when we have better support for in-progress
-  // downloads (e.g., after pause(), resume() and cancel() are implemented)
-
-  // Check multiple query properties.
-  // We could make this testing arbitrarily complicated...
-  // We already tested combining fields with obvious interactions above
-  // (e.g., filename and filenameRegex or startTime and startedBefore/After)
-  // so now just throw as many fields as we can at a single search and
-  // make sure a simple case still works.
-  yield checkSearch({
-    url: TXT_URL,
-    urlRegex: "download",
-    filename: downloadPath(TXT_FILE),
-    filenameRegex: "download",
-    query: ["download"],
-    startedAfter: time1.valueOf().toString(),
-    startedBefore: time2.valueOf().toString(),
-    totalBytes: TXT_LEN,
-    totalBytesGreater: 0,
-    totalBytesLess: BIG_LEN,
-    mime: "text/plain",
-    fileSize: TXT_LEN,
-  }, ["txt1"], "many properties");
-
-  // Check simple orderBy (forward and backward).
-  yield checkSearch({orderBy: ["startTime"]}, ["txt1", "txt2", "html1", "html2"], "orderBy startTime", true);
-  yield checkSearch({orderBy: ["-startTime"]}, ["html2", "html1", "txt2", "txt1"], "orderBy -startTime", true);
-
-  // Check orderBy with multiple fields.
-  // NB: TXT_URL and HTML_URL differ only in extension and .html precedes .txt
-  yield checkSearch({orderBy: ["url", "-startTime"]}, ["html2", "html1", "txt2", "txt1"], "orderBy with multiple fields", true);
-
-  // Check orderBy with limit.
-  yield checkSearch({orderBy: ["url"], limit: 1}, ["html1"], "orderBy with limit", true);
-
-  // Check bad arguments.
-  function* checkBadSearch(query, pattern, description) {
-    let msg = yield search(query);
-    is(msg.status, "error", "search() failed");
-    ok(pattern.test(msg.errmsg), `error message for ${description} was correct (${msg.errmsg}).`);
-  }
-
-  yield checkBadSearch("myquery", /Incorrect argument type/, "query is not an object");
-  yield checkBadSearch({bogus: "boo"}, /Unexpected property/, "query contains an unknown field");
-  yield checkBadSearch({query: "query string"}, /Expected array/, "query.query is a string");
-  yield checkBadSearch({startedBefore: "i am not a number"}, /Type error/, "query.startedBefore is not a valid time");
-  yield checkBadSearch({startedAfter: "i am not a number"}, /Type error/, "query.startedAfter is not a valid time");
-  yield checkBadSearch({endedBefore: "i am not a number"}, /Type error/, "query.endedBefore is not a valid time");
-  yield checkBadSearch({endedAfter: "i am not a number"}, /Type error/, "query.endedAfter is not a valid time");
-  yield checkBadSearch({urlRegex: "["}, /Invalid urlRegex/, "query.urlRegexp is not a valid regular expression");
-  yield checkBadSearch({filenameRegex: "["}, /Invalid filenameRegex/, "query.filenameRegexp is not a valid regular expression");
-  yield checkBadSearch({orderBy: "startTime"}, /Expected array/, "query.orderBy is not an array");
-  yield checkBadSearch({orderBy: ["bogus"]}, /Invalid orderBy field/, "query.orderBy references a non-existent field");
-});
-
-</script>
-
-</body>
-</html>