Bug 1239708: Improve awesomebar autofill. Part 5: xpcshell tests. r?mak draft
authorDrew Willcoxon <adw@mozilla.com>
Mon, 14 May 2018 11:27:19 -0700
changeset 794917 521df249727e5fead2a5beea351af95ccd789451
parent 794916 bc660adfc85e78d69ab254b9d2d9867657bac8b7
child 794918 f0c0cfa7006f322f875d20a49d5f2f1d0378ad52
push id109819
push userbmo:adw@mozilla.com
push dateMon, 14 May 2018 20:01:28 +0000
reviewersmak
bugs1239708
milestone62.0a1
Bug 1239708: Improve awesomebar autofill. Part 5: xpcshell tests. r?mak MozReview-Commit-ID: 4mMyFeay69T
services/sync/tests/unit/test_history_store.js
toolkit/components/places/tests/head_common.js
toolkit/components/places/tests/migration/test_current_from_v47.js
toolkit/components/places/tests/migration/xpcshell.ini
toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js
toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
toolkit/components/places/tests/unifiedcomplete/test_417798.js
toolkit/components/places/tests/unifiedcomplete/test_418257.js
toolkit/components/places/tests/unifiedcomplete/test_422277.js
toolkit/components/places/tests/unifiedcomplete/test_PlacesSearchAutocompleteProvider.js
toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js
toolkit/components/places/tests/unifiedcomplete/test_autofill_default_behavior.js
toolkit/components/places/tests/unifiedcomplete/test_autofill_origins.js
toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js
toolkit/components/places/tests/unifiedcomplete/test_autofill_urls.js
toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js
toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js
toolkit/components/places/tests/unifiedcomplete/test_casing.js
toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js
toolkit/components/places/tests/unifiedcomplete/test_enabled.js
toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js
toolkit/components/places/tests/unifiedcomplete/test_escape_self.js
toolkit/components/places/tests/unifiedcomplete/test_ignore_protocol.js
toolkit/components/places/tests/unifiedcomplete/test_keywords.js
toolkit/components/places/tests/unifiedcomplete/test_match_beginning.js
toolkit/components/places/tests/unifiedcomplete/test_preloaded_sites.js
toolkit/components/places/tests/unifiedcomplete/test_query_url.js
toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js
toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js
toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js
toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js
toolkit/components/places/tests/unifiedcomplete/test_trimming.js
toolkit/components/places/tests/unifiedcomplete/test_typed.js
toolkit/components/places/tests/unifiedcomplete/test_word_boundary_search.js
toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js
toolkit/components/places/tests/unifiedcomplete/xpcshell.ini
toolkit/components/places/tests/unit/test_adaptive_bug527311.js
toolkit/components/places/tests/unit/test_hosts_triggers.js
toolkit/components/places/tests/unit/test_origins.js
toolkit/components/places/tests/unit/test_preventive_maintenance.js
toolkit/components/places/tests/unit/test_sql_function_origin.js
toolkit/components/places/tests/unit/xpcshell.ini
toolkit/components/search/tests/xpcshell/test_resultDomain.js
--- a/services/sync/tests/unit/test_history_store.js
+++ b/services/sync/tests/unit/test_history_store.js
@@ -159,19 +159,19 @@ add_task(async function test_null_title(
 add_task(async function test_invalid_records() {
   _("Make sure we handle invalid URLs in places databases gracefully.");
   await PlacesUtils.withConnectionWrapper("test_invalid_record", async function(db) {
     await db.execute(
       "INSERT INTO moz_places "
       + "(url, url_hash, title, rev_host, visit_count, last_visit_date) "
       + "VALUES ('invalid-uri', hash('invalid-uri'), 'Invalid URI', '.', 1, " + TIMESTAMP3 + ")"
     );
-    // Trigger the update on moz_hosts by deleting the added rows from
-    // moz_updatehostsinsert_temp
-    await db.execute("DELETE FROM moz_updatehostsinsert_temp");
+    // Trigger the update to the moz_origin tables by deleting the added rows
+    // from moz_updateoriginsinsert_temp
+    await db.executeCached("DELETE FROM moz_updateoriginsinsert_temp");
     // Add the corresponding visit to retain database coherence.
     await db.execute(
       "INSERT INTO moz_historyvisits "
       + "(place_id, visit_date, visit_type, session) "
       + "VALUES ((SELECT id FROM moz_places WHERE url_hash = hash('invalid-uri') AND url = 'invalid-uri'), "
       + TIMESTAMP3 + ", " + Ci.nsINavHistoryService.TRANSITION_TYPED + ", 1)"
     );
   });
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -1,14 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-const CURRENT_SCHEMA_VERSION = 47;
+const CURRENT_SCHEMA_VERSION = 48;
 const FIRST_UPGRADABLE_SCHEMA_VERSION = 30;
 
 const NS_APP_USER_PROFILE_50_DIR = "ProfD";
 
 // Shortcuts to transitions type.
 const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK;
 const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED;
 const TRANSITION_BOOKMARK = Ci.nsINavHistoryService.TRANSITION_BOOKMARK;
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/migration/test_current_from_v47.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function setup() {
+  await setupPlacesDatabase("places_v43.sqlite");
+});
+
+add_task(async function database_is_valid() {
+  // Accessing the database for the first time triggers migration.
+  Assert.equal(PlacesUtils.history.databaseStatus,
+               PlacesUtils.history.DATABASE_STATUS_UPGRADED);
+
+  let db = await PlacesUtils.promiseDBConnection();
+  Assert.equal((await db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
+});
+
+add_task(async function test_origins() {
+  await TestUtils.waitForCondition(() => {
+    return !Services.prefs.getBoolPref("places.database.migrateV48Frecencies", false);
+  }, "Waiting for v48 origin frecencies to be migrated", 100, 3000);
+
+  let db = await PlacesUtils.promiseDBConnection();
+
+  // Collect origins.
+  let rows = await db.execute(`
+    SELECT id, prefix, host, frecency
+    FROM moz_origins
+    ORDER BY id ASC;
+  `);
+  Assert.notEqual(rows.length, 0);
+  let origins = rows.map(r => ({
+    id: r.getResultByName("id"),
+    prefix: r.getResultByName("prefix"),
+    host: r.getResultByName("host"),
+    frecency: r.getResultByName("frecency"),
+  }));
+
+  // Get moz_places.
+  rows = await db.execute(`
+    SELECT get_prefix(url) AS prefix, get_host_and_port(url) AS host,
+           origin_id, frecency
+    FROM moz_places;
+  `);
+  Assert.notEqual(rows.length, 0);
+
+  let seenOriginIDs = [];
+  let maxFrecencyByOriginID = {};
+
+  // Make sure moz_places.origin_id refers to the right origins.
+  for (let row of rows) {
+    let originID = row.getResultByName("origin_id");
+    let origin = origins.find(o => o.id == originID);
+    Assert.ok(origin);
+    Assert.equal(origin.prefix, row.getResultByName("prefix"));
+    Assert.equal(origin.host, row.getResultByName("host"));
+
+    seenOriginIDs.push(originID);
+
+    let frecency = row.getResultByName("frecency");
+    if (!(originID in maxFrecencyByOriginID)) {
+      maxFrecencyByOriginID[originID] = frecency;
+    } else {
+      maxFrecencyByOriginID[originID] =
+        Math.max(frecency, maxFrecencyByOriginID[originID]);
+    }
+  }
+
+  for (let origin of origins) {
+    // Make sure each origin corresponds to at least one moz_place.
+    Assert.ok(seenOriginIDs.includes(origin.id));
+
+    // moz_origins.frecency should be the max frecency of all moz_places with
+    // the origin.
+    Assert.equal(origin.frecency, maxFrecencyByOriginID[origin.id]);
+  }
+
+  // Make sure moz_hosts was emptied.
+  rows = await db.execute(`
+    SELECT *
+    FROM moz_hosts;
+  `);
+  Assert.equal(rows.length, 0);
+});
--- a/toolkit/components/places/tests/migration/xpcshell.ini
+++ b/toolkit/components/places/tests/migration/xpcshell.ini
@@ -20,8 +20,9 @@ support-files =
 [test_current_from_v35.js]
 [test_current_from_v36.js]
 [test_current_from_v38.js]
 [test_current_from_v41.js]
 [test_current_from_v42.js]
 [test_current_from_v43.js]
 [test_current_from_v45.js]
 [test_current_from_v46.js]
+[test_current_from_v47.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js
@@ -0,0 +1,642 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* import-globals-from ../head_common.js */
+/* import-globals-from ./head_autocomplete.js */
+
+function addAutofillTasks(origins) {
+  // Helpful reminder of the `autofilled` and `completed` properties in the
+  // object passed to check_autocomplete:
+  //
+  //   autofilled: expected input.value after autofill
+  //    completed: expected input.value after autofill and enter is pressed
+  //
+  // `completed` is the URL that the controller sets to input.value, and the URL
+  // that will ultimately be loaded when you press enter.  When you press enter,
+  // the code path is:
+  //
+  //   (1) urlbar.handleEnter
+  //   (2) nsAutoCompleteController::HandleEnter
+  //   (3) nsAutoCompleteController::EnterMatch (sets input.value)
+  //   (4) input.onTextEntered
+  //   (5) urlbar.handleCommand (loads input.value)
+
+  let path;
+  let search;
+  let searchCase;
+  let comment;
+  if (origins) {
+    path = "/";
+    search = "ex";
+    searchCase = "EX";
+    comment = "example.com";
+  } else {
+    path = "/foo";
+    search = "example.com/f";
+    searchCase = "EXAMPLE.COM/f";
+    comment = "example.com/foo";
+  }
+
+  let host = "example.com";
+  let url = host + path;
+
+  add_task(async function init() {
+    await cleanup();
+  });
+
+  // "ex" should match http://example.com/.
+  add_task(async function basic() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "http://" + url,
+      matches: [{
+        value: url,
+        comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "EX" should match http://example.com/.
+  add_task(async function basicCase() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: searchCase,
+      autofilled: searchCase + url.substr(searchCase.length),
+      completed: "http://" + url,
+      matches: [{
+        value: url,
+        comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "ex" should match http://www.example.com/.
+  add_task(async function noWWWShouldMatchWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://www." + url,
+    }]);
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "http://www." + url,
+      matches: [{
+        value: url,
+        comment: "www." + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "EX" should match http://www.example.com/.
+  add_task(async function noWWWShouldMatchWWWCase() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://www." + url,
+    }]);
+    await check_autocomplete({
+      search: searchCase,
+      autofilled: searchCase + url.substr(searchCase.length),
+      completed: "http://www." + url,
+      matches: [{
+        value: url,
+        comment: "www." + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "www.ex" should *not* match http://example.com/.
+  add_task(async function wwwShouldNotMatchNoWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: "www." + search,
+      matches: [],
+    });
+    await cleanup();
+  });
+
+  // "http://ex" should match http://example.com/.
+  add_task(async function prefix() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: "http://" + search,
+      autofilled: "http://" + url,
+      completed: "http://" + url,
+      matches: [{
+        value: "http://" + url,
+        comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "HTTP://EX" should match http://example.com/.
+  add_task(async function prefixCase() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: "HTTP://" + searchCase,
+      autofilled: "HTTP://" + searchCase + url.substr(searchCase.length),
+      completed: "http://" + url,
+      matches: [{
+        value: "http://" + url,
+        comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "http://ex" should match http://www.example.com/.
+  add_task(async function prefixNoWWWShouldMatchWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://www." + url,
+    }]);
+    await check_autocomplete({
+      search: "http://" + search,
+      autofilled: "http://" + url,
+      completed: "http://www." + url,
+      matches: [{
+        value: "http://" + url,
+        comment: "www." + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "HTTP://EX" should match http://www.example.com/.
+  add_task(async function prefixNoWWWShouldMatchWWWCase() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://www." + url,
+    }]);
+    await check_autocomplete({
+      search: "HTTP://" + searchCase,
+      autofilled: "HTTP://" + searchCase + url.substr(searchCase.length),
+      completed: "http://www." + url,
+      matches: [{
+        value: "http://" + url,
+        comment: "www." + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "http://www.ex" should *not* match http://example.com/.
+  add_task(async function prefixWWWShouldNotMatchNoWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: "http://www." + search,
+      matches: [],
+    });
+    await cleanup();
+  });
+
+  // "http://ex" should *not* match https://example.com/.
+  add_task(async function httpPrefixShouldNotMatchHTTPS() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://" + url,
+    }]);
+    await check_autocomplete({
+      search: "http://" + search,
+      matches: [{
+        value: "https://" + url,
+        comment: "test visit for https://" + url,
+        style: ["favicon"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "ex" should match https://example.com/.
+  add_task(async function httpsBasic() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://" + url,
+    }]);
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://" + url,
+      matches: [{
+        value: url,
+        comment: "https://" + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "ex" should match https://www.example.com/.
+  add_task(async function httpsNoWWWShouldMatchWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://www." + url,
+    }]);
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://www." + url,
+      matches: [{
+        value: url,
+        comment: "https://www." + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "www.ex" should *not* match https://example.com/.
+  add_task(async function httpsWWWShouldNotMatchNoWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://" + url,
+    }]);
+    await check_autocomplete({
+      search: "www." + search,
+      matches: [],
+    });
+    await cleanup();
+  });
+
+  // "https://ex" should match https://example.com/.
+  add_task(async function httpsPrefix() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://" + url,
+    }]);
+    await check_autocomplete({
+      search: "https://" + search,
+      autofilled: "https://" + url,
+      completed: "https://" + url,
+      matches: [{
+        value: "https://" + url,
+        comment: "https://" + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "https://ex" should match https://www.example.com/.
+  add_task(async function httpsPrefixNoWWWShouldMatchWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://www." + url,
+    }]);
+    await check_autocomplete({
+      search: "https://" + search,
+      autofilled: "https://" + url,
+      completed: "https://www." + url,
+      matches: [{
+        value: "https://" + url,
+        comment: "https://www." + comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // "https://www.ex" should *not* match https://example.com/.
+  add_task(async function httpsPrefixWWWShouldNotMatchNoWWW() {
+    await PlacesTestUtils.addVisits([{
+      uri: "https://" + url,
+    }]);
+    await check_autocomplete({
+      search: "https://www." + search,
+      matches: [],
+    });
+    await cleanup();
+  });
+
+  // "https://ex" should *not* match http://example.com/.
+  add_task(async function httpsPrefixShouldNotMatchHTTP() {
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: "https://" + search,
+      matches: [{
+        value: "http://" + url,
+        comment: "test visit for http://" + url,
+        style: ["favicon"],
+      }],
+    });
+    await cleanup();
+  });
+
+  // Autofill should respond to frecency changes.
+  add_task(async function frecency() {
+    // Start with an http visit.  It should be completed.
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "http://" + url,
+      matches: [{
+        value: url,
+        comment,
+        style: ["autofill", "heuristic"],
+      }],
+    });
+
+    // Add two https visits.  https should now be completed.
+    for (let i = 0; i < 2; i++) {
+      await PlacesTestUtils.addVisits([
+        { uri: "https://" + url },
+      ]);
+    }
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://" + url,
+      matches: [
+        {
+          value: url,
+          comment: "https://" + comment,
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: "http://" + url,
+          comment: "test visit for http://" + url,
+          style: ["favicon"],
+        },
+      ],
+    });
+
+    // Add two more http visits, three total.  http should now be completed
+    // again.
+    for (let i = 0; i < 2; i++) {
+      await PlacesTestUtils.addVisits([
+        { uri: "http://" + url },
+      ]);
+    }
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "http://" + url,
+      matches: [
+        {
+          value: url,
+          comment,
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: "https://" + url,
+          comment: "test visit for https://" + url,
+          style: ["favicon"],
+        },
+      ],
+    });
+
+    // Add four www https visits.  www https should now be completed.
+    for (let i = 0; i < 4; i++) {
+      await PlacesTestUtils.addVisits([
+        { uri: "https://www." + url },
+      ]);
+    }
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://www." + url,
+      matches: [
+        {
+          value: url,
+          comment: "https://www." + comment,
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: "http://" + url,
+          comment: "test visit for http://" + url,
+          style: ["favicon"],
+        },
+        {
+          value: "https://" + url,
+          comment: "test visit for https://" + url,
+          style: ["favicon"],
+        },
+      ],
+    });
+
+    // Remove the www https page.
+    await PlacesUtils.history.remove([
+      "https://www." + url,
+    ]);
+
+    // http should now be completed again.
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "http://" + url,
+      matches: [
+        {
+          value: url,
+          comment,
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: "https://" + url,
+          comment: "test visit for https://" + url,
+          style: ["favicon"],
+        },
+      ],
+    });
+
+    // Remove the http page.
+    await PlacesUtils.history.remove([
+      "http://" + url,
+    ]);
+
+    // https should now be completed again.
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://" + url,
+      matches: [
+        {
+          value: url,
+          comment: "https://" + comment,
+          style: ["autofill", "heuristic"],
+        },
+      ],
+    });
+
+    // Add a visit with a different host so that "ex" doesn't autofill it.
+    // https://example.com/ should still have a higher frecency though, so it
+    // should still be autofilled.
+    await PlacesTestUtils.addVisits([
+      { uri: "https://not-" + url },
+    ]);
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://" + url,
+      matches: [
+        {
+          value: url,
+          comment: "https://" + comment,
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: "https://not-" + url,
+          comment: "test visit for https://not-" + url,
+          style: ["favicon"],
+        },
+      ],
+    });
+
+    // Now add 10 more visits to the different host so that the frecency of
+    // https://example.com/ falls below the autofill threshold.  It should not
+    // be autofilled now.
+    for (let i = 0; i < 10; i++) {
+      await PlacesTestUtils.addVisits([
+        { uri: "https://not-" + url },
+      ]);
+    }
+
+    // Enable actions to make sure that the failure to make an autofill match
+    // does not interrupt creating another type of heuristic match, in this case
+    // a search (for "ex") in the `origins` case, and a visit in the `!origins`
+    // case.
+    await check_autocomplete({
+      search,
+      searchParam: "enable-actions",
+      matches: [
+        origins ?
+          makeSearchMatch(search, { style: ["heuristic"] }) :
+          makeVisitMatch(search, "http://" + search, { heuristic: true }),
+        {
+          value: "https://not-" + url,
+          comment: "test visit for https://not-" + url,
+          style: ["favicon"],
+        },
+        {
+          value: "https://" + url,
+          comment: "test visit for https://" + url,
+          style: ["favicon"],
+        },
+      ],
+    });
+
+    // Remove the visits to the different host.
+    await PlacesUtils.history.remove([
+      "https://not-" + url,
+    ]);
+
+    // https should be completed again.
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "https://" + url,
+      matches: [
+        {
+          value: url,
+          comment: "https://" + comment,
+          style: ["autofill", "heuristic"],
+        },
+      ],
+    });
+
+    // Remove the https visits.
+    await PlacesUtils.history.remove([
+      "https://" + url,
+    ]);
+
+    // Now nothing should be completed.
+    await check_autocomplete({
+      search,
+      matches: [],
+    });
+
+    await cleanup();
+  });
+
+  // Autofill should respect the browser.urlbar.suggest.history pref -- i.e., it
+  // should complete only bookmarked pages when that pref is false.
+  add_task(async function bookmarked() {
+    // Force only bookmarked pages to be suggested and therefore only bookmarked
+    // pages to be completed.
+    Services.prefs.setBoolPref("browser.urlbar.suggest.history", false);
+
+    // Add a non-bookmarked page.  It should not be suggested or completed.
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search,
+      matches: [],
+    });
+
+    // Bookmark the page.  It should be suggested and completed.
+    await addBookmark({
+      uri: "http://" + url,
+    });
+    await check_autocomplete({
+      search,
+      autofilled: url,
+      completed: "http://" + url,
+      matches: [
+        {
+          value: url,
+          comment,
+          style: ["autofill", "heuristic"],
+        },
+      ],
+    });
+
+    await cleanup();
+  });
+
+  // Same as previous but the search contains a prefix.
+  add_task(async function bookmarkedPrefix() {
+    // Force only bookmarked pages to be suggested and therefore only bookmarked
+    // pages to be completed.
+    Services.prefs.setBoolPref("browser.urlbar.suggest.history", false);
+
+    // Add a non-bookmarked page.  It should not be suggested or completed.
+    await PlacesTestUtils.addVisits([{
+      uri: "http://" + url,
+    }]);
+    await check_autocomplete({
+      search: "http://" + search,
+      matches: [],
+    });
+
+    // Bookmark the page.  It should be suggested and completed.
+    await addBookmark({
+      uri: "http://" + url,
+    });
+    await check_autocomplete({
+      search: "http://" + search,
+      autofilled: "http://" + url,
+      completed: "http://" + url,
+      matches: [
+        {
+          value: "http://" + url,
+          comment,
+          style: ["autofill", "heuristic"],
+        },
+      ],
+    });
+
+    await cleanup();
+  });
+}
--- a/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
+++ b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
@@ -10,24 +10,31 @@ ChromeUtils.import("resource://testing-c
 // Import common head.
 {
   /* import-globals-from ../head_common.js */
   let commonFile = do_get_file("../head_common.js", false);
   let uri = Services.io.newFileURI(commonFile);
   Services.scriptloader.loadSubScript(uri.spec, this);
 }
 
+// Add a lazy getter for common autofill test tasks used by some tests.
+{
+  /* import-globals-from ./autofill_tasks.js */
+  let file = do_get_file("autofill_tasks.js", false);
+  let uri = Services.io.newFileURI(file);
+  XPCOMUtils.defineLazyScriptGetter(this, "addAutofillTasks", uri.spec);
+}
+
 // Put any other stuff relative to this test folder below.
 
 const TITLE_SEARCH_ENGINE_SEPARATOR = " \u00B7\u2013\u00B7 ";
 
 async function cleanup() {
   Services.prefs.clearUserPref("browser.urlbar.autocomplete.enabled");
   Services.prefs.clearUserPref("browser.urlbar.autoFill");
-  Services.prefs.clearUserPref("browser.urlbar.autoFill.typed");
   Services.prefs.clearUserPref("browser.urlbar.autoFill.searchEngines");
   let suggestPrefs = [
     "history",
     "bookmark",
     "history.onlyTyped",
     "openpage",
     "searches",
   ];
@@ -100,41 +107,46 @@ AutoCompleteInput.prototype = {
  * A helper for check_autocomplete to check a specific match against data from
  * the controller.
  *
  * @param {Object} match The expected match for the result, in the following form:
  * {
  *   uri: {nsIURI} The expected uri.
  *   title: {String} The title of the entry.
  *   tags: {String} The tags for the entry.
- *   style: {String} The style of the entry.
+ *   style: {Array} The style of the entry.
  * }
  * @param {Object} result The result to compare the result against with the same
  *                        properties as the match param.
  * @returns {boolean} Returns true if the result matches.
  */
 async function _check_autocomplete_matches(match, result) {
-  let { uri, title, tags, style } = match;
+  let { uri, tags, style } = match;
+  let title = match.comment || match.title;
+
   if (tags)
     title += " \u2013 " + tags.sort().join(", ");
   if (style)
     style = style.sort();
   else
     style = ["favicon"];
 
-  info(`Checking against expected "${uri.spec}", comment: "${title}", style: "${style}"`);
-  // Got a match on both uri and title?
-  if (stripPrefix(uri.spec) != stripPrefix(result.value) || title != result.comment) {
+  let actual = { value: result.value, comment: result.comment };
+  let expected = { value: match.value || uri.spec, comment: title };
+  info(`Checking match: ` +
+       `actual=${JSON.stringify(actual)} ... ` +
+       `expected=${JSON.stringify(expected)}`);
+  if (actual.value != expected.value || actual.comment != expected.comment) {
     return false;
   }
 
   let actualStyle = result.style.split(/\s+/).sort();
   if (style)
     Assert.equal(actualStyle.toString(), style.toString(), "Match should have expected style");
-  if (uri.spec.startsWith("moz-action:")) {
+  if (uri && uri.spec.startsWith("moz-action:")) {
     Assert.ok(actualStyle.includes("action"), "moz-action results should always have 'action' in their style");
   }
 
   if (match.icon) {
     await compareFavicons(result.image, match.icon, "Match should have the expected icon");
   }
 
   return true;
@@ -226,17 +238,17 @@ async function check_autocomplete(test) 
 
       for (let i = firstIndexToCheck; i < controller.matchCount; i++) {
         let result = {
           value: controller.getValueAt(i),
           comment: controller.getCommentAt(i),
           style: controller.getStyleAt(i),
           image: controller.getImageAt(i),
         };
-        info(`Found value: "${result.value}", comment: "${result.comment}", style: "${result.style}" in results...`);
+        info(`Actual result at index ${i}: ${JSON.stringify(result)}`);
         let lowerBound = test.checkSorting ? i : firstIndexToCheck;
         let upperBound = test.checkSorting ? i + 1 : matches.length;
         let found = false;
         for (let j = lowerBound; j < upperBound; ++j) {
           // Skip processed expected results
           if (matches[j] == undefined)
             continue;
           if (await _check_autocomplete_matches(matches[j], result)) {
--- a/toolkit/components/places/tests/unifiedcomplete/test_417798.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_417798.js
@@ -17,35 +17,49 @@ add_task(async function test_javascript_
                       title: "Title with javascript:" });
 
   info("Match non-javascript: with plain search");
   await check_autocomplete({
     search: "a",
     matches: [ { uri: uri1, title: "Title with javascript:" } ]
   });
 
-  info("Match non-javascript: with almost javascript:");
+  info("Match non-javascript: with 'javascript'");
   await check_autocomplete({
     search: "javascript",
     matches: [ { uri: uri1, title: "Title with javascript:" } ]
   });
 
-  info("Match javascript:");
+  info("Match nothing with 'javascript:'");
   await check_autocomplete({
     search: "javascript:",
-    matches: [ { uri: uri1, title: "Title with javascript:" },
-               { uri: uri2, title: "Title with javascript:", style: [ "bookmark" ]} ]
+    matches: []
   });
 
-  info("Match nothing with non-first javascript:");
+  info("Match nothing with '5 javascript:'");
   await check_autocomplete({
     search: "5 javascript:",
     matches: [ ]
   });
 
-  info("Match javascript: with multi-word search");
+  info("Match non-javascript: with 'a javascript:'");
+  await check_autocomplete({
+    search: "a javascript:",
+    matches: [ { uri: uri1, title: "Title with javascript:" } ]
+  });
+
+  info("Match non-javascript: and javascript: with 'javascript: a'");
+  await check_autocomplete({
+    search: "javascript: a",
+    matches: [
+      { uri: uri1, title: "Title with javascript:" },
+      { uri: uri2, title: "Title with javascript:", style: ["bookmark"] },
+    ]
+  });
+
+  info("Match javascript: with 'javascript: 5'");
   await check_autocomplete({
     search: "javascript: 5",
     matches: [ { uri: uri2, title: "Title with javascript:", style: [ "bookmark" ]} ]
   });
 
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_418257.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_418257.js
@@ -3,17 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Test bug 418257 by making sure tags are returned with the title as part of
  * the "comment" if there are tags even if we didn't match in the tags. They
  * are separated from the title by a endash.
  */
 
-add_task(async function test_javascript_match() {
+add_task(async function test() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+
   let uri1 = NetUtil.newURI("http://page1");
   let uri2 = NetUtil.newURI("http://page2");
   let uri3 = NetUtil.newURI("http://page3");
   let uri4 = NetUtil.newURI("http://page4");
   await PlacesTestUtils.addVisits([
     { uri: uri1, title: "tagged" },
     { uri: uri2, title: "tagged" },
     { uri: uri3, title: "tagged" },
--- a/toolkit/components/places/tests/unifiedcomplete/test_422277.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_422277.js
@@ -2,17 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Test bug 422277 to make sure bad escaped uris don't get escaped. This makes
  * sure we don't hit an assertion for "not a UTF8 string".
  */
 
-add_task(async function test_javascript_match() {
+add_task(async function test() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+
   info("Bad escaped uri stays escaped");
   let uri1 = NetUtil.newURI("http://site/%EAid");
   await PlacesTestUtils.addVisits([ { uri: uri1, title: "title" } ]);
   await check_autocomplete({
     search: "site",
     matches: [ { uri: uri1, title: "title" } ]
   });
   await cleanup();
--- a/toolkit/components/places/tests/unifiedcomplete/test_PlacesSearchAutocompleteProvider.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_PlacesSearchAutocompleteProvider.js
@@ -30,17 +30,18 @@ add_task(async function no_match() {
 
 add_task(async function hide_search_engine_nomatch() {
   let engine = await promiseDefaultSearchEngine();
   let token = engine.getResultDomain();
   let promiseTopic = promiseSearchTopic("engine-changed");
   Services.search.removeEngine(engine);
   await promiseTopic;
   Assert.ok(engine.hidden);
-  Assert.equal(null, await PlacesSearchAutocompleteProvider.findMatchByToken(token.substr(0, 1)));
+  let match = await PlacesSearchAutocompleteProvider.findMatchByToken(token.substr(0, 1));
+  Assert.ok(!match || match.token != token);
 });
 
 add_task(async function add_search_engine_match() {
   let promiseTopic = promiseSearchTopic("engine-added");
   Assert.equal(null, await PlacesSearchAutocompleteProvider.findMatchByToken("bacon"));
   Services.search.addEngineWithDetails("bacon", "", "pork", "Search Bacon",
                                        "GET", "http://www.bacon.moz/?search={searchTerms}");
   await promiseTopic;
--- a/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js
@@ -6,146 +6,63 @@
 
 const PREF_AUTOCOMPLETE_ENABLED = "browser.urlbar.autocomplete.enabled";
 
 add_task(async function test_disabling_autocomplete() {
   info("Check disabling autocomplete disables autofill");
   Services.prefs.setBoolPref(PREF_AUTOCOMPLETE_ENABLED, false);
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://visit.mozilla.org"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "vis",
     autofilled: "vis",
     completed: "vis"
   });
   await cleanup();
 });
 
 add_task(async function test_urls_order() {
   info("Add urls, check for correct order");
   let places = [{ uri: NetUtil.newURI("http://visit1.mozilla.org") },
-                { uri: NetUtil.newURI("http://visit2.mozilla.org"),
-                  transition: TRANSITION_TYPED }];
+                { uri: NetUtil.newURI("http://visit2.mozilla.org") }];
   await PlacesTestUtils.addVisits(places);
   await check_autocomplete({
     search: "vis",
     autofilled: "visit2.mozilla.org/",
-    completed: "visit2.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_ignore_prefix() {
-  info("Add urls, make sure www and http are ignored");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://www.visit1.mozilla.org"));
-  await check_autocomplete({
-    search: "visit1",
-    autofilled: "visit1.mozilla.org/",
-    completed: "visit1.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_after_host() {
-  info("Autocompleting after an existing host completes to the url");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://www.visit3.mozilla.org"));
-  await check_autocomplete({
-    search: "visit3.mozilla.org/",
-    autofilled: "visit3.mozilla.org/",
-    completed: "visit3.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_respect_www() {
-  info("Searching for www.me should yield www.me.mozilla.org/");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://www.me.mozilla.org"));
-  await check_autocomplete({
-    search: "www.me",
-    autofilled: "www.me.mozilla.org/",
-    completed: "www.me.mozilla.org/"
+    completed: "http://visit2.mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_bookmark_first() {
   info("With a bookmark and history, the query result should be the bookmark");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
   await addBookmark({ uri: NetUtil.newURI("http://bookmark1.mozilla.org/") });
   await PlacesTestUtils.addVisits(NetUtil.newURI("http://bookmark1.mozilla.org/foo"));
   await check_autocomplete({
     search: "bookmark",
     autofilled: "bookmark1.mozilla.org/",
-    completed: "bookmark1.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_full_path() {
-  info("Check to make sure we get the proper results with full paths");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  let places = [{ uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=delicious") },
-                { uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=smokey") }];
-  await PlacesTestUtils.addVisits(places);
-  await check_autocomplete({
-    search: "smokey",
-    autofilled: "smokey.mozilla.org/",
-    completed: "smokey.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_complete_to_slash() {
-  info("Check to make sure we autocomplete to the following '/'");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  let places = [{ uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=delicious") },
-                { uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=smokey") }];
-  await PlacesTestUtils.addVisits(places);
-  await check_autocomplete({
-    search: "smokey.mozilla.org/fo",
-    autofilled: "smokey.mozilla.org/foo/",
-    completed: "http://smokey.mozilla.org/foo/",
-  });
-  await cleanup();
-});
-
-add_task(async function test_complete_to_slash_with_www() {
-  info("Check to make sure we autocomplete to the following '/'");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  let places = [{ uri: NetUtil.newURI("http://www.smokey.mozilla.org/foo/bar/baz?bacon=delicious") },
-                { uri: NetUtil.newURI("http://www.smokey.mozilla.org/foo/bar/baz?bacon=smokey") }];
-  await PlacesTestUtils.addVisits(places);
-  await check_autocomplete({
-    search: "smokey.mozilla.org/fo",
-    autofilled: "smokey.mozilla.org/foo/",
-    completed: "http://www.smokey.mozilla.org/foo/",
+    completed: "http://bookmark1.mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_complete_querystring() {
   info("Check to make sure we autocomplete after ?");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
   await PlacesTestUtils.addVisits(NetUtil.newURI("http://smokey.mozilla.org/foo?bacon=delicious"));
   await check_autocomplete({
     search: "smokey.mozilla.org/foo?",
     autofilled: "smokey.mozilla.org/foo?bacon=delicious",
     completed: "http://smokey.mozilla.org/foo?bacon=delicious",
   });
   await cleanup();
 });
 
 add_task(async function test_complete_fragment() {
   info("Check to make sure we autocomplete after #");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
   await PlacesTestUtils.addVisits(NetUtil.newURI("http://smokey.mozilla.org/foo?bacon=delicious#bar"));
   await check_autocomplete({
     search: "smokey.mozilla.org/foo?bacon=delicious#bar",
     autofilled: "smokey.mozilla.org/foo?bacon=delicious#bar",
     completed: "http://smokey.mozilla.org/foo?bacon=delicious#bar",
   });
   await cleanup();
 });
deleted file mode 100644
--- a/toolkit/components/places/tests/unifiedcomplete/test_autofill_default_behavior.js
+++ /dev/null
@@ -1,322 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Test autoFill for different default behaviors.
- */
-
-add_task(async function test_default_behavior_host() {
-  let uri1 = NetUtil.newURI("http://typed/");
-  let uri2 = NetUtil.newURI("http://visited/");
-  let uri3 = NetUtil.newURI("http://bookmarked/");
-  let uri4 = NetUtil.newURI("http://tpbk/");
-  let uri5 = NetUtil.newURI("http://tagged/");
-  let uri6 = NetUtil.newURI("https://secure/");
-
-  await PlacesTestUtils.addVisits([
-    { uri: uri1, title: "typed", transition: TRANSITION_TYPED },
-    { uri: uri2, title: "visited" },
-    { uri: uri4, title: "tpbk", transition: TRANSITION_TYPED },
-    { uri: uri6, title: "secure", transition: TRANSITION_TYPED },
-  ]);
-  await addBookmark( { uri: uri3, title: "bookmarked" } );
-  await addBookmark( { uri: uri4, title: "tpbk" } );
-  await addBookmark( { uri: uri5, title: "title", tags: ["foo"] } );
-
-  await setFaviconForPage(uri1, "chrome://global/skin/icons/info.svg");
-  await setFaviconForPage(uri3, "chrome://global/skin/icons/error-16.png");
-  await setFaviconForPage(uri6, "chrome://global/skin/icons/question-16.png");
-
-  // RESTRICT TO HISTORY.
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history", true);
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", false);
-  Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false);
-
-  info("Restrict history, common visit, should not autoFill");
-  await check_autocomplete({
-    search: "vi",
-    matches: [ { uri: uri2, title: "visited" } ],
-    autofilled: "vi",
-    completed: "vi"
-  });
-
-  info("Restrict history, typed visit, should autoFill");
-  await check_autocomplete({
-    search: "ty",
-    matches: [ { uri: uri1, title: "typed", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/info.svg" } ],
-    autofilled: "typed/",
-    completed: "typed/"
-  });
-
-  info("Restrict history, secure typed visit, should autoFill with https");
-  await check_autocomplete({
-    search: "secure",
-    matches: [ { uri: uri6, title: "https://secure", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/question-16.png" } ],
-    autofilled: "secure/",
-    completed: "https://secure/"
-  });
-
-  // Don't autoFill this one cause it's not typed.
-  info("Restrict history, bookmark, should not autoFill");
-  await check_autocomplete({
-    search: "bo",
-    matches: [ ],
-    autofilled: "bo",
-    completed: "bo"
-  });
-
-  // Note we don't show this one cause it's not typed.
-  info("Restrict history, typed bookmark, should autoFill");
-  await check_autocomplete({
-    search: "tp",
-    matches: [ { uri: uri4, title: "tpbk", style: [ "autofill", "heuristic" ] } ],
-    autofilled: "tpbk/",
-    completed: "tpbk/"
-  });
-
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-
-  // We are not restricting on typed, so we autoFill the bookmark even if we
-  // are restricted to history.  We accept that cause not doing that
-  // would be a perf hit and the privacy implications are very weak.
-  info("Restrict history, bookmark, autoFill.typed = false, should autoFill");
-  await check_autocomplete({
-    search: "bo",
-    matches: [ { uri: uri3, title: "bookmarked", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/error-16.png" } ],
-    autofilled: "bookmarked/",
-    completed: "bookmarked/"
-  });
-
-  info("Restrict history, common visit, autoFill.typed = false, should autoFill");
-  await check_autocomplete({
-    search: "vi",
-    matches: [ { uri: uri2, title: "visited", style: [ "autofill", "heuristic" ] } ],
-    autofilled: "visited/",
-    completed: "visited/"
-  });
-
-  // RESTRICT TO TYPED.
-  // This should basically ignore autoFill.typed and acts as if it would be set.
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", true);
-
-  // Typed behavior basically acts like history, but filters on typed.
-  info("Restrict typed, common visit, autoFill.typed = false, should not autoFill");
-  await check_autocomplete({
-    search: "vi",
-    matches: [ ],
-    autofilled: "vi",
-    completed: "vi"
-  });
-
-  info("Restrict typed, typed visit, autofill.typed = false, should autoFill");
-  await check_autocomplete({
-    search: "ty",
-    matches: [ { uri: uri1, title: "typed", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/info.svg"} ],
-    autofilled: "typed/",
-    completed: "typed/"
-  });
-
-  info("Restrict typed, bookmark, autofill.typed = false, should not autoFill");
-  await check_autocomplete({
-    search: "bo",
-    matches: [ ],
-    autofilled: "bo",
-    completed: "bo"
-  });
-
-  info("Restrict typed, typed bookmark, autofill.typed = false, should autoFill");
-  await check_autocomplete({
-    search: "tp",
-    matches: [ { uri: uri4, title: "tpbk", style: [ "autofill", "heuristic" ] } ],
-    autofilled: "tpbk/",
-    completed: "tpbk/"
-  });
-
-  // RESTRICT BOOKMARKS.
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history", false);
-  Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true);
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", true);
-
-  info("Restrict bookmarks, common visit, should not autoFill");
-  await check_autocomplete({
-    search: "vi",
-    matches: [ ],
-    autofilled: "vi",
-    completed: "vi"
-  });
-
-  info("Restrict bookmarks, typed visit, should not autoFill");
-  await check_autocomplete({
-    search: "ty",
-    matches: [ ],
-    autofilled: "ty",
-    completed: "ty"
-  });
-
-  // Don't autoFill this one cause it's not typed.
-  info("Restrict bookmarks, bookmark, should not autoFill");
-  await check_autocomplete({
-    search: "bo",
-    matches: [ { uri: uri3, title: "bookmarked", style: [ "bookmark" ],
-                 icon: "chrome://global/skin/icons/error-16.png"} ],
-    autofilled: "bo",
-    completed: "bo"
-  });
-
-  // Note we don't show this one cause it's not typed.
-  info("Restrict bookmarks, typed bookmark, should autoFill");
-  await check_autocomplete({
-    search: "tp",
-    matches: [ { uri: uri4, title: "tpbk", style: [ "autofill", "heuristic" ] } ],
-    autofilled: "tpbk/",
-    completed: "tpbk/"
-  });
-
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-
-  info("Restrict bookmarks, bookmark, autofill.typed = false, should autoFill");
-  await check_autocomplete({
-    search: "bo",
-    matches: [ { uri: uri3, title: "bookmarked", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/error-16.png" } ],
-    autofilled: "bookmarked/",
-    completed: "bookmarked/"
-  });
-
-  // Don't autofill because it's a title.
-  info("Restrict bookmarks, title, autofill.typed = false, should not autoFill");
-  await check_autocomplete({
-    search: "# ta",
-    matches: [ ],
-    autofilled: "# ta",
-    completed: "# ta"
-  });
-
-  // Don't autofill because it's a tag.
-  info("Restrict bookmarks, tag, autofill.typed = false, should not autoFill");
-  await check_autocomplete({
-    search: "+ ta",
-    matches: [ { uri: uri5, title: "title", tags: [ "foo" ], style: [ "tag" ] } ],
-    autofilled: "+ ta",
-    completed: "+ ta"
-  });
-
-  await cleanup();
-});
-
-add_task(async function test_default_behavior_url() {
-  let uri1 = NetUtil.newURI("http://typed/ty/");
-  let uri2 = NetUtil.newURI("http://visited/vi/");
-  let uri3 = NetUtil.newURI("http://bookmarked/bo/");
-  let uri4 = NetUtil.newURI("http://tpbk/tp/");
-
-  await PlacesTestUtils.addVisits([
-    { uri: uri1, title: "typed", transition: TRANSITION_TYPED },
-    { uri: uri2, title: "visited" },
-    { uri: uri4, title: "tpbk", transition: TRANSITION_TYPED },
-  ]);
-  await addBookmark( { uri: uri3, title: "bookmarked" } );
-  await addBookmark( { uri: uri4, title: "tpbk" } );
-
-  await setFaviconForPage(uri1, "chrome://global/skin/icons/info.svg");
-  await setFaviconForPage(uri3, "chrome://global/skin/icons/error-16.png");
-
-  // RESTRICT TO HISTORY.
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history", true);
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", false);
-  Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false);
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", true);
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false);
-
-  info("URL: Restrict history, common visit, should not autoFill");
-  await check_autocomplete({
-    search: "visited/v",
-    matches: [ { uri: uri2, title: "visited" } ],
-    autofilled: "visited/v",
-    completed: "visited/v"
-  });
-
-  info("URL: Restrict history, typed visit, should autoFill");
-  await check_autocomplete({
-    search: "typed/t",
-    matches: [ { uri: uri1, title: "typed/ty/", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/info.svg"} ],
-    autofilled: "typed/ty/",
-    completed: "http://typed/ty/"
-  });
-
-  // Don't autoFill this one cause it's not typed.
-  info("URL: Restrict history, bookmark, should not autoFill");
-  await check_autocomplete({
-    search: "bookmarked/b",
-    matches: [ ],
-    autofilled: "bookmarked/b",
-    completed: "bookmarked/b"
-  });
-
-  // Note we don't show this one cause it's not typed.
-  info("URL: Restrict history, typed bookmark, should autoFill");
-  await check_autocomplete({
-    search: "tpbk/t",
-    matches: [ { uri: uri4, title: "tpbk/tp/", style: [ "autofill", "heuristic" ] } ],
-    autofilled: "tpbk/tp/",
-    completed: "http://tpbk/tp/"
-  });
-
-  // RESTRICT BOOKMARKS.
-  Services.prefs.setBoolPref("browser.urlbar.suggest.history", false);
-  Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true);
-
-  info("URL: Restrict bookmarks, common visit, should not autoFill");
-  await check_autocomplete({
-    search: "visited/v",
-    matches: [ ],
-    autofilled: "visited/v",
-    completed: "visited/v"
-  });
-
-  info("URL: Restrict bookmarks, typed visit, should not autoFill");
-  await check_autocomplete({
-    search: "typed/t",
-    matches: [ ],
-    autofilled: "typed/t",
-    completed: "typed/t"
-  });
-
-  // Don't autoFill this one cause it's not typed.
-  info("URL: Restrict bookmarks, bookmark, should not autoFill");
-  await check_autocomplete({
-    search: "bookmarked/b",
-    matches: [ { uri: uri3, title: "bookmarked", style: [ "bookmark" ],
-                 icon: "chrome://global/skin/icons/error-16.png" } ],
-    autofilled: "bookmarked/b",
-    completed: "bookmarked/b"
-  });
-
-  // Note we don't show this one cause it's not typed.
-  info("URL: Restrict bookmarks, typed bookmark, should autoFill");
-  await check_autocomplete({
-    search: "tpbk/t",
-    matches: [ { uri: uri4, title: "tpbk/tp/", style: [ "autofill", "heuristic" ] } ],
-    autofilled: "tpbk/tp/",
-    completed: "http://tpbk/tp/"
-  });
-
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-
-  info("URL: Restrict bookmarks, bookmark, autofill.typed = false, should autoFill");
-  await check_autocomplete({
-    search: "bookmarked/b",
-    matches: [ { uri: uri3, title: "bookmarked/bo/", style: [ "autofill", "heuristic" ],
-                 icon: "chrome://global/skin/icons/error-16.png" } ],
-    autofilled: "bookmarked/bo/",
-    completed: "http://bookmarked/bo/"
-  });
-
-  await cleanup();
-});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_origins.js
@@ -0,0 +1,106 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+addAutofillTasks(true);
+
+// "example.com/" should match http://example.com/.  i.e., the search string
+// should be treated as if it didn't have the trailing slash.
+add_task(async function trailingSlash() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com/",
+  }]);
+  await check_autocomplete({
+    search: "example.com/",
+    autofilled: "example.com/",
+    completed: "http://example.com/",
+    matches: [{
+      value: "example.com/",
+      comment: "example.com/",
+      style: ["autofill", "heuristic"],
+    }],
+  });
+  await cleanup();
+});
+
+// "example.com/" should match http://www.example.com/.  i.e., the search string
+// should be treated as if it didn't have the trailing slash.
+add_task(async function trailingSlashWWW() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://www.example.com/",
+  }]);
+  await check_autocomplete({
+    search: "example.com/",
+    autofilled: "example.com/",
+    completed: "http://www.example.com/",
+    matches: [{
+      value: "example.com/",
+      comment: "www.example.com/",
+      style: ["autofill", "heuristic"],
+    }],
+  });
+  await cleanup();
+});
+
+// "ex" should match http://example.com:8888/, and the port should be completed.
+add_task(async function port() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com:8888/",
+  }]);
+  await check_autocomplete({
+    search: "ex",
+    autofilled: "example.com:8888/",
+    completed: "http://example.com:8888/",
+    matches: [{
+      value: "example.com:8888/",
+      comment: "example.com:8888",
+      style: ["autofill", "heuristic"],
+    }],
+  });
+  await cleanup();
+});
+
+// "example.com:8" should match http://example.com:8888/, and the port should
+// be completed.
+add_task(async function portPartial() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com:8888/",
+  }]);
+  await check_autocomplete({
+    search: "example.com:8",
+    autofilled: "example.com:8888/",
+    completed: "http://example.com:8888/",
+    matches: [{
+      value: "example.com:8888/",
+      comment: "example.com:8888",
+      style: ["autofill", "heuristic"],
+    }],
+  });
+  await cleanup();
+});
+
+// "example.com:89" should *not* match http://example.com:8888/.
+add_task(async function portNoMatch1() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com:8888/",
+  }]);
+  await check_autocomplete({
+    search: "example.com:89",
+    matches: [],
+  });
+  await cleanup();
+});
+
+// "example.com:9" should *not* match http://example.com:8888/.
+add_task(async function portNoMatch2() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com:8888/",
+  }]);
+  await check_autocomplete({
+    search: "example.com:9",
+    matches: [],
+  });
+  await cleanup();
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js
@@ -0,0 +1,169 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// The autoFill.searchEngines pref autofills the domains of engines registered
+// with the search service.  That's what this test checks.  It's a different
+// path in UnifiedComplete.js from normal moz_places autofill, which is tested
+// in test_autofill_origins.js and test_autofill_urls.js.
+
+"use strict";
+
+add_task(async function searchEngines() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
+
+  let schemes = ["http", "https"];
+  for (let i = 0; i < schemes.length; i++) {
+    let scheme = schemes[i];
+    Services.search.addEngineWithDetails("TestEngine", "", "", "", "GET",
+                                         scheme + "://www.example.com/");
+    let engine = Services.search.getEngineByName("TestEngine");
+    engine.addParam("q", "{searchTerms}", null);
+
+    await check_autocomplete({
+      search: "ex",
+      autofilled: "example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: "example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: "example.com",
+      autofilled: "example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: "example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: "example.com/",
+      autofilled: "example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: "example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: "www.ex",
+      autofilled: "www.example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: "www.example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: "www.example.com",
+      autofilled: "www.example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: "www.example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: "www.example.com/",
+      autofilled: "www.example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: "www.example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: scheme + "://ex",
+      autofilled: scheme + "://example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: scheme + "://example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: scheme + "://example.com",
+      autofilled: scheme + "://example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: scheme + "://example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: scheme + "://example.com/",
+      autofilled: scheme + "://example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: scheme + "://example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: scheme + "://www.ex",
+      autofilled: scheme + "://www.example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: scheme + "://www.example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: scheme + "://www.example.com",
+      autofilled: scheme + "://www.example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: scheme + "://www.example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    await check_autocomplete({
+      search: scheme + "://www.example.com/",
+      autofilled: scheme + "://www.example.com/",
+      completed: scheme + "://www.example.com/",
+      matches: [{
+        value: scheme + "://www.example.com/",
+        comment: "TestEngine",
+        style: ["heuristic", "priority-search"],
+      }],
+    });
+
+    let otherScheme = schemes[(i + 1) % schemes.length];
+    await check_autocomplete({
+      search: otherScheme + "://ex",
+      matches: [],
+    });
+    await check_autocomplete({
+      search: otherScheme + "://www.ex",
+      matches: [],
+    });
+
+    Services.search.removeEngine(engine);
+  }
+
+  await cleanup();
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_urls.js
@@ -0,0 +1,55 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+addAutofillTasks(false);
+
+// "example.com/foo/" should match http://example.com/foo/.
+add_task(async function multipleSlashes() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com/foo/",
+  }]);
+  await check_autocomplete({
+    search: "example.com/foo/",
+    autofilled: "example.com/foo/",
+    completed: "http://example.com/foo/",
+    matches: [{
+      value: "example.com/foo/",
+      comment: "example.com/foo/",
+      style: ["autofill", "heuristic"],
+    }],
+  });
+  await cleanup();
+});
+
+// "example.com:8888/f" should match http://example.com:8888/foo.
+add_task(async function port() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com:8888/foo",
+  }]);
+  await check_autocomplete({
+    search: "example.com:8888/f",
+    autofilled: "example.com:8888/foo",
+    completed: "http://example.com:8888/foo",
+    matches: [{
+      value: "example.com:8888/foo",
+      comment: "example.com:8888/foo",
+      style: ["autofill", "heuristic"],
+    }],
+  });
+  await cleanup();
+});
+
+// "example.com:8999/f" should *not* match http://example.com:8888/foo.
+add_task(async function portNoMatch() {
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com:8888/foo",
+  }]);
+  await check_autocomplete({
+    search: "example.com:8999/f",
+    matches: [],
+  });
+  await cleanup();
+});
--- a/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js
@@ -40,18 +40,18 @@ add_task(async function test_searchEngin
                                        "GET", "http://cake.search/");
   let engine = Services.search.getEngineByName("CakeSearch");
   engine.addParam("q", "{searchTerms}", null);
   registerCleanupFunction(() => Services.search.removeEngine(engine));
 
   info("Should autoFill search engine if search string does not contains a space");
   await check_autocomplete({
     search: "ca",
-    autofilled: "cake.search",
-    completed: "http://cake.search"
+    autofilled: "cake.search/",
+    completed: "http://cake.search/"
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_prefix_space_noautofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
   Services.search.addEngineWithDetails("CupcakeSearch", "", "", "",
@@ -131,49 +131,47 @@ add_task(async function test_searchEngin
   let engine = Services.search.getEngineByName("BeanSearch");
   engine.addParam("q", "{searchTerms}", null);
   registerCleanupFunction(() => Services.search.removeEngine(engine));
 
 
   info("Should autoFill search engine if search string has matching prefix.");
   await check_autocomplete({
     search: "http://www.be",
-    autofilled: "http://www.bean.search",
-    completed: "http://www.bean.search"
+    autofilled: "http://www.bean.search/",
+    completed: "http://www.bean.search/"
   });
 
   info("Should autoFill search engine if search string has www prefix.");
   await check_autocomplete({
     search: "www.be",
-    autofilled: "www.bean.search",
-    completed: "http://www.bean.search"
+    autofilled: "www.bean.search/",
+    completed: "http://www.bean.search/"
   });
 
   info("Should autoFill search engine if search string has matching scheme.");
   await check_autocomplete({
     search: "http://be",
-    autofilled: "http://bean.search",
-    completed: "http://www.bean.search"
+    autofilled: "http://bean.search/",
+    completed: "http://www.bean.search/"
   });
 
   await cleanup();
 });
 
 add_task(async function test_prefix_autofill() {
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://moz.org/test/"),
-    transition: TRANSITION_TYPED
   });
 
   info("Should not try to autoFill in-the-middle if a search is canceled immediately");
   await check_autocomplete({
     incompleteSearch: "moz",
     search: "mozi",
     autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
+    completed: "http://mozilla.org/"
   });
 
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js
@@ -6,36 +6,71 @@ add_task(async function test_protocol_tr
   for (let prot of ["http", "https", "ftp"]) {
     let visit = {
       // Include the protocol in the query string to ensure we get matches (see bug 1059395)
       uri: NetUtil.newURI(prot + "://www.mozilla.org/test/?q=" + prot + encodeURIComponent("://") + "www.foo"),
       title: "Test title",
       transition: TRANSITION_TYPED
     };
     await PlacesTestUtils.addVisits(visit);
-    let matches = [{uri: visit.uri, title: visit.title}];
+
+    let input = prot + "://www.";
+    info("Searching for: " + input);
+    await check_autocomplete({
+      search: input,
+      matches: [
+        {
+          value: prot + "://www.mozilla.org/",
+          comment: prot == "http" ? "www.mozilla.org"
+                                  : prot + "://www.mozilla.org",
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: visit.uri.spec,
+          comment: visit.title,
+          style: ["favicon"],
+        }
+      ],
+    });
+
+    input = "www.";
+    info("Searching for: " + input);
+    await check_autocomplete({
+      search: input,
+      matches: [
+        {
+          value: "www.mozilla.org/",
+          comment: prot == "http" ? "www.mozilla.org"
+                                  : prot + "://www.mozilla.org",
+          style: ["autofill", "heuristic"],
+        },
+        {
+          value: visit.uri.spec,
+          comment: visit.title,
+          style: ["favicon"],
+        }
+      ],
+    });
 
     let inputs = [
       prot + "://",
       prot + ":// ",
       prot + ":// mo",
       prot + "://mo te",
-      prot + "://www.",
       prot + "://www. ",
       prot + "://www. mo",
       prot + "://www.mo te",
-      "www.",
       "www. ",
       "www. mo",
       "www.mo te"
     ];
-    for (let input of inputs) {
+    for (input of inputs) {
       info("Searching for: " + input);
       await check_autocomplete({
         search: input,
-        matches
+        matches: [{uri: visit.uri, title: visit.title}],
       });
     }
 
     await cleanup();
   }
 });
 
--- a/toolkit/components/places/tests/unifiedcomplete/test_casing.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_casing.js
@@ -1,157 +1,146 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(async function test_casing_1() {
   info("Searching for cased entry 1");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "MOZ",
     autofilled: "MOZilla.org/",
-    completed: "mozilla.org/"
+    completed: "http://mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_casing_2() {
   info("Searching for cased entry 2");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.org/T",
     autofilled: "mozilla.org/T",
     completed: "mozilla.org/T"
   });
   await cleanup();
 });
 
 add_task(async function test_casing_3() {
   info("Searching for cased entry 3");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.org/T",
     autofilled: "mozilla.org/Test/",
     completed: "http://mozilla.org/Test/"
   });
   await cleanup();
 });
 
 add_task(async function test_casing_4() {
   info("Searching for cased entry 4");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mOzilla.org/t",
     autofilled: "mOzilla.org/t",
     completed: "mOzilla.org/t"
   });
   await cleanup();
 });
 
 add_task(async function test_casing_5() {
   info("Searching for cased entry 5");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mOzilla.org/T",
     autofilled: "mOzilla.org/Test/",
     completed: "http://mozilla.org/Test/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_casing() {
   info("Searching for untrimmed cased entry");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "http://mOz",
     autofilled: "http://mOzilla.org/",
     completed: "http://mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_www_casing() {
   info("Searching for untrimmed cased entry with www");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://www.mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "http://www.mOz",
     autofilled: "http://www.mOzilla.org/",
     completed: "http://www.mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_path_casing() {
   info("Searching for untrimmed cased entry with path");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "http://mOzilla.org/t",
     autofilled: "http://mOzilla.org/t",
     completed: "http://mOzilla.org/t"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_path_casing_2() {
   info("Searching for untrimmed cased entry with path 2");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "http://mOzilla.org/T",
     autofilled: "http://mOzilla.org/Test/",
     completed: "http://mozilla.org/Test/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_path_www_casing() {
   info("Searching for untrimmed cased entry with www and path");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://www.mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "http://www.mOzilla.org/t",
     autofilled: "http://www.mOzilla.org/t",
     completed: "http://www.mOzilla.org/t"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_path_www_casing_2() {
   info("Searching for untrimmed cased entry with www and path 2");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://www.mozilla.org/Test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "http://www.mOzilla.org/T",
     autofilled: "http://www.mOzilla.org/Test/",
     completed: "http://www.mozilla.org/Test/"
   });
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js
@@ -2,38 +2,44 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Ensure inline autocomplete doesn't return zero frecency pages.
 
 add_task(async function test_dupe_urls() {
   info("Searching for urls with dupes should only show one");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/"),
-    transition: TRANSITION_TYPED
   }, {
     uri: NetUtil.newURI("http://mozilla.org/?")
   });
   await check_autocomplete({
     search: "moz",
     autofilled: "mozilla.org/",
-    completed:  "mozilla.org/",
-    matches: [ { uri: NetUtil.newURI("http://mozilla.org/"),
-                 title: "mozilla.org",
-                 style: [ "autofill", "heuristic" ] } ]
+    completed:  "http://mozilla.org/",
+    matches: [
+      {
+        value: "mozilla.org/",
+        comment: "mozilla.org",
+        style: ["autofill", "heuristic"]
+      },
+    ],
   });
 });
 
 add_task(async function test_dupe_secure_urls() {
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://example.org/"),
-    transition: TRANSITION_TYPED
   }, {
     uri: NetUtil.newURI("https://example.org/?")
   });
   await check_autocomplete({
     search: "exam",
     autofilled: "example.org/",
     completed: "https://example.org/",
-    matches: [ { uri: NetUtil.newURI("https://example.org/"),
-                 title: "https://example.org",
-                 style: [ "autofill", "heuristic" ] } ]
+    matches: [
+      {
+        value: "example.org/",
+        comment: "https://example.org",
+        style: ["autofill", "heuristic"]
+      },
+    ],
   });
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_enabled.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_enabled.js
@@ -1,11 +1,13 @@
 add_task(async function test_enabled() {
   // Test for bug 471903 to make sure searching in autocomplete can be turned on
   // and off. Also test bug 463535 for pref changing search.
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+
   let uri = NetUtil.newURI("http://url/0");
   await PlacesTestUtils.addVisits([ { uri, title: "title" } ]);
 
   info("plain search");
   await check_autocomplete({
     search: "url",
     matches: [ { uri, title: "title" } ]
   });
--- a/toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js
@@ -20,19 +20,23 @@ add_task(async function test_encoded_tri
   info("Searching for over encoded url should not break it");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"),
     title: "https://www.mozilla.com/search/top/?q=%25%32%35",
     transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.com/search/top/?q=%25%32%35",
-    matches: [ { uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"),
-                 title: "https://www.mozilla.com/search/top/?q=%25%32%35",
-                 style: [ "autofill", "heuristic" ] }],
+    matches: [
+      {
+        value: "mozilla.com/search/top/?q=%25%32%35",
+        comment: "https://www.mozilla.com/search/top/?q=%25%32%35",
+        style: ["autofill", "heuristic"],
+      },
+    ],
     autofilled: "mozilla.com/search/top/?q=%25%32%35",
     completed: "https://www.mozilla.com/search/top/?q=%25%32%35"
   });
   await cleanup();
 });
 
 add_task(async function test_encoded_partial() {
   info("Searching for over encoded url should not break it");
--- a/toolkit/components/places/tests/unifiedcomplete/test_escape_self.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_escape_self.js
@@ -3,16 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Test bug 422698 to make sure searches with urls from the location bar
  * correctly match itself when it contains escaped characters.
  */
 
 add_task(async function test_escape() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+
   let uri1 = NetUtil.newURI("http://unescapeduri/");
   let uri2 = NetUtil.newURI("http://escapeduri/%40/");
   await PlacesTestUtils.addVisits([
     { uri: uri1, title: "title" },
     { uri: uri2, title: "title" }
   ]);
 
   info("Unescaped location matches itself");
--- a/toolkit/components/places/tests/unifiedcomplete/test_ignore_protocol.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_ignore_protocol.js
@@ -2,16 +2,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Test bug 424509 to make sure searching for "h" doesn't match "http" of urls.
  */
 
 add_task(async function test_escape() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+
   let uri1 = NetUtil.newURI("http://site/");
   let uri2 = NetUtil.newURI("http://happytimes/");
   await PlacesTestUtils.addVisits([
     { uri: uri1, title: "title" },
     { uri: uri2, title: "title" }
   ]);
 
   info("Searching for h matches site and not http://");
--- a/toolkit/components/places/tests/unifiedcomplete/test_keywords.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_keywords.js
@@ -1,77 +1,72 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(async function test_non_keyword() {
   info("Searching for non-keyworded entry should autoFill it");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/") });
   await check_autocomplete({
     search: "moz",
     autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
+    completed: "http://mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_keyword() {
   info("Searching for keyworded entry should not autoFill it");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" });
   await check_autocomplete({
     search: "moz",
     autofilled: "moz",
     completed: "moz",
   });
   await cleanup();
 });
 
 add_task(async function test_more_than_keyword() {
   info("Searching for more than keyworded entry should autoFill it");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" });
   await check_autocomplete({
     search: "mozi",
     autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
+    completed: "http://mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_less_than_keyword() {
   info("Searching for less than keyworded entry should autoFill it");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" });
   await check_autocomplete({
     search: "mo",
     autofilled: "mozilla.org/",
-    completed: "mozilla.org/",
+    completed: "http://mozilla.org/",
   });
   await cleanup();
 });
 
 add_task(async function test_keyword_casing() {
   info("Searching for keyworded entry is case-insensitive");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" });
   await check_autocomplete({
     search: "MoZ",
     autofilled: "MoZ",
     completed: "MoZ"
   });
   await cleanup();
--- a/toolkit/components/places/tests/unifiedcomplete/test_match_beginning.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_match_beginning.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Test bug 451760 which allows matching only at the beginning of urls or
  * titles to simulate Firefox 2 functionality.
  */
 
 add_task(async function test_match_beginning() {
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false);
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
 
   let uri1 = NetUtil.newURI("http://x.com/y");
   let uri2 = NetUtil.newURI("https://y.com/x");
   await PlacesTestUtils.addVisits([
     { uri: uri1, title: "a b" },
     { uri: uri2, title: "b a" }
   ]);
 
--- a/toolkit/components/places/tests/unifiedcomplete/test_preloaded_sites.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_preloaded_sites.js
@@ -131,149 +131,145 @@ add_task(async function test_scheme_and_
 
   let titlesMap = new Map(sites);
 
   autocompleteObject.populatePreloadedSiteStorage(sites);
 
   let tests =
   [
     // User typed,
-    // Inline autofill,
-    // Substitute after enter is pressed,
+    // Inline autofill (`autofilled`),
+    // Substitute after enter is pressed (`completed`),
     //   [List matches, with sorting]
     //   not tested if omitted
     //   !!! first one is always an autofill entry !!!
 
     [// Protocol by itself doesn't match anything
     "https://",
     "https://",
     "https://",
       []
     ],
 
-    [// "www." by itself doesn't match anything
-    "www.",
+    [
     "www.",
-    "www.",
-      []
+    "www.ooops-https-www.com/",
+    "https://www.ooops-https-www.com/",
+      [
+        ["www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
+        "HTTP://www.ooops-HTTP-www.com/",
+        "https://www.bar.com/",
+      ]
     ],
 
-    [// Protocol with "www." by itself doesn't match anything
-    "http://www.",
+    [
     "http://www.",
-    "http://www.",
-      []
+    "http://www.ooops-http-www.com/",
+    "http://www.ooops-http-www.com/",
+      [
+        ["http://www.ooops-http-www.com/", "www.ooops-http-www.com"],
+      ]
     ],
 
-    [// ftp: - ignore
+    [
     "ftp://ooops",
     "ftp://ooops",
     "ftp://ooops",
       []
     ],
 
-    [// Edge case: no "www." in search string, autofill and list entries with "www."
+    [
     "ww",
     "www.ooops-https-www.com/",
-    "https://www.ooops-https-www.com/", // 2nd in list, but has priority as strict
+    "https://www.ooops-https-www.com/",
       [
-      ["https://www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
-      "HTTP://www.ooops-HTTP-www.com/",
-      ["https://foo.com/", "Title with www", ["preloaded-top-site"]],
-      "https://www.bar.com/",
+        ["www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
+        "HTTP://www.ooops-HTTP-www.com/",
+        ["https://foo.com/", "Title with www", ["preloaded-top-site"]],
+        "https://www.bar.com/",
       ]
     ],
 
-    [// Strict match, no "www."
+    [
     "ooops",
-    "ooops-https.com/",
-    "https://ooops-https.com/", // 2nd in list, but has priority as strict
-      [// List entries are not sorted (initial sorting preserved)
-       // except autofill entry is on top as always
-      ["https://ooops-https.com/", "https://ooops-https.com"],
-      "https://www.ooops-https-www.com/",
-      "HTTP://ooops-HTTP.com/",
-      "HTTP://www.ooops-HTTP-www.com/",
+    "ooops-https-www.com/",
+    "https://www.ooops-https-www.com/",
+      [
+        ["ooops-https-www.com/", "https://www.ooops-https-www.com"],
+        "https://ooops-https.com/",
+        "HTTP://ooops-HTTP.com/",
+        "HTTP://www.ooops-HTTP-www.com/",
       ]
     ],
 
-    [// Strict match with "www."
+    [
     "www.ooops",
     "www.ooops-https-www.com/",
     "https://www.ooops-https-www.com/",
-      [// Matches with "www." sorted on top
-      ["https://www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
-      "HTTP://www.ooops-HTTP-www.com/",
-      "https://ooops-https.com/",
-      "HTTP://ooops-HTTP.com/",
+      [
+        ["www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
+        "HTTP://www.ooops-HTTP-www.com/",
       ]
     ],
 
-    [// Loose match: search no "www.", result with "www."
+    [
     "ooops-https-www",
     "ooops-https-www.com/",
     "https://www.ooops-https-www.com/",
       [
-      ["https://www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
+        ["ooops-https-www.com/", "https://www.ooops-https-www.com"],
       ]
     ],
 
-    [// Loose match: search "www.", no-www site gets "www."
+    [
+    "www.ooops-https.",
+    "www.ooops-https.",
     "www.ooops-https.",
-    "www.ooops-https.com/",
-    "https://www.ooops-https.com/",
-      [// Only autofill entry gets "www."
-      ["https://www.ooops-https.com/", "https://www.ooops-https.com"],
-      "https://ooops-https.com/", // List entry with preloaded top URL for match site
+      []
+    ],
+
+    [
+    "https://ooops",
+    "https://ooops-https-www.com/",
+    "https://www.ooops-https-www.com/",
+      [
+        ["https://ooops-https-www.com/", "https://www.ooops-https-www.com"],
+        "https://ooops-https.com/",
       ]
     ],
 
-    [// Explicit protocol, no "www."
-    "https://ooops",
-    "https://ooops-https.com/",
-    "https://ooops-https.com/",
-      [
-      ["https://ooops-https.com/", "https://ooops-https.com"],
-      "https://www.ooops-https-www.com/",
-      ]
-    ],
-
-    [// Explicit protocol, with "www."
+    [
     "https://www.ooops",
     "https://www.ooops-https-www.com/",
     "https://www.ooops-https-www.com/",
       [
-      ["https://www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
-      "https://ooops-https.com/",
+        ["https://www.ooops-https-www.com/", "https://www.ooops-https-www.com"],
       ]
     ],
 
-    [// Explicit HTTP protocol, no-www site gets "www."
+    [
+    "http://www.ooops-http.",
     "http://www.ooops-http.",
-    "http://www.ooops-http.com/",
-    "http://www.ooops-http.com/",
-      [
-      ["HTTP://www.ooops-HTTP.com/", "www.ooops-http.com"],
-      "HTTP://ooops-HTTP.com/",
-      ]
+    "http://www.ooops-http.",
+      []
     ],
 
-    [// Wrong protocol
+    [
     "http://ooops-https",
     "http://ooops-https",
     "http://ooops-https",
       []
     ],
   ];
 
   function toMatch(entry, index) {
     if (Array.isArray(entry)) {
       return {
-        uri: NetUtil.newURI(entry[0]),
-        title: entry[1],
+        value: entry[0],
+        comment: entry[1],
         style: entry[2] || ["autofill", "heuristic", "preloaded-top-site"],
       };
     }
     return {
       uri: NetUtil.newURI(entry),
       title: titlesMap.get(entry),
       style: ["preloaded-top-site"],
     };
@@ -313,8 +309,28 @@ add_task(async function test_data_file()
   await check_autocomplete({
     search: uri.host,
     autofilled: uri.host + "/",
     completed: uri.spec,
   });
 
   await cleanup();
 });
+
+add_task(async function test_partial_scheme() {
+  // "tt" should not result in a match of "ttps://whatever.com/".
+  autocompleteObject.populatePreloadedSiteStorage([
+    ["http://www.ttt.com/", "Test"],
+  ]);
+  await check_autocomplete({
+    search: "tt",
+    autofilled: "ttt.com/",
+    completed: "http://www.ttt.com/",
+    matches: [
+      {
+        value: "ttt.com/",
+        comment: "www.ttt.com",
+        style: ["autofill", "heuristic", "preloaded-top-site"],
+      },
+    ],
+  });
+  await cleanup();
+});
--- a/toolkit/components/places/tests/unifiedcomplete/test_query_url.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_query_url.js
@@ -1,68 +1,61 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(async function test_no_slash() {
   info("Searching for host match without slash should match host");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://file.org/test/"),
-    transition: TRANSITION_TYPED
   }, {
     uri: NetUtil.newURI("file:///c:/test.html"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "file",
     autofilled: "file.org/",
-    completed: "file.org/"
+    completed: "http://file.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_w_slash() {
-  info("Searching match with slash at the end should do nothing");
+  info("Searching match with slash at the end should match host");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://file.org/test/"),
-    transition: TRANSITION_TYPED
   }, {
     uri: NetUtil.newURI("file:///c:/test.html"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "file.org/",
     autofilled: "file.org/",
-    completed: "file.org/"
+    completed: "http://file.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_middle() {
   info("Searching match with slash in the middle should match url");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://file.org/test/"),
-    transition: TRANSITION_TYPED
   }, {
     uri: NetUtil.newURI("file:///c:/test.html"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "file.org/t",
     autofilled: "file.org/test/",
     completed: "http://file.org/test/"
   });
   await cleanup();
 });
 
 add_task(async function test_nonhost() {
   info("Searching for non-host match without slash should not match url");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("file:///c:/test.html"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "file",
     autofilled: "file",
     completed: "file"
   });
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js
@@ -17,33 +17,32 @@ add_task(async function test_searchEngin
   await PlacesTestUtils.addVisits(visits);
   await addBookmark({ uri, title: "Example bookmark" });
   await PlacesTestUtils.promiseAsyncUpdates();
   ok(frecencyForUrl(uri) > 10000, "Added URI should have expected high frecency");
 
   info("Check search domain is autoFilled even if there's an higher frecency match");
   await check_autocomplete({
     search: "my",
-    autofilled: "my.search.com",
-    completed: "http://my.search.com"
+    autofilled: "my.search.com/",
+    completed: "http://my.search.com/"
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_noautoFill() {
   let engineName = "engine-rel-searchform.xml";
   let engine = await addTestEngine(engineName);
   equal(engine.searchForm, "http://example.com/?search");
 
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
   await PlacesTestUtils.addVisits(NetUtil.newURI("http://example.com/my/"));
 
   info("Check search domain is not autoFilled if it matches a visited domain");
   await check_autocomplete({
     search: "example",
     autofilled: "example.com/",
-    completed: "example.com/"
+    completed: "http://example.com/"
   });
 
   await cleanup();
 });
 
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js
@@ -777,16 +777,17 @@ add_task(async function avoid_url_sugges
     ],
   });
 
   await cleanUpSuggestions();
 });
 
 add_task(async function avoid_http_url_suggestions() {
   Services.prefs.setBoolPref(SUGGEST_PREF, true);
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
 
   setSuggestionsFn(searchStr => {
     return [searchStr + "ed"];
   });
 
   await check_autocomplete({
     search: "htt",
     searchParam: "enable-actions",
@@ -848,49 +849,37 @@ add_task(async function avoid_http_url_s
       },
     ],
   });
 
   await check_autocomplete({
     search: "http:",
     searchParam: "enable-actions",
     matches: [
-      {
-        uri: makeActionURI("visiturl", { url: "http://http/", input: "http:" }),
-        style: [ "action", "visiturl", "heuristic" ],
-        title: "http://http/",
-      },
+      makeSearchMatch("http:", { engineName: ENGINE_NAME, heuristic: true }),
     ],
   });
 
   await check_autocomplete({
     search: "https:",
     searchParam: "enable-actions",
     matches: [
-      {
-        uri: makeActionURI("visiturl", { url: "http://https/", input: "https:" }),
-        style: [ "action", "visiturl", "heuristic" ],
-        title: "http://https/",
-      },
+      makeSearchMatch("https:", { engineName: ENGINE_NAME, heuristic: true }),
     ],
   });
 
   // Check FTP enabled
   Services.prefs.setBoolPref("network.ftp.enabled", true);
   registerCleanupFunction(() => Services.prefs.clearUserPref("network.ftp.enabled"));
 
   await check_autocomplete({
     search: "ftp:",
     searchParam: "enable-actions",
     matches: [
-      {
-        uri: makeActionURI("visiturl", { url: "http://ftp/", input: "ftp:" }),
-        style: [ "action", "visiturl", "heuristic" ],
-        title: "http://ftp/",
-      },
+      makeSearchMatch("ftp:", { engineName: ENGINE_NAME, heuristic: true }),
     ],
   });
 
   await check_autocomplete({
     search: "ftp:/",
     searchParam: "enable-actions",
     matches: [
       {
--- a/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js
@@ -36,23 +36,26 @@ add_task(async function test_swap_protoc
     { uri: uri2, title: "title" },
     { uri: uri3, title: "title" },
     { uri: uri4, title: "title" },
     { uri: uri5, title: "title" },
     { uri: uri6, title: "title" }
   ];
 
   // Disable autoFill to avoid handling the first result.
-  Services.prefs.setBoolPref("browser.urlbar.autoFill", "false");
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false);
 
-  info("http://www.site matches all site");
+  info("http://www.site matches 'www.site' pages");
   await check_autocomplete({
     search: "http://www.site",
-    matches: allMatches
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+    ]
   });
 
   info("http://site matches all site");
   await check_autocomplete({
     search: "http://site",
     matches: allMatches
   });
 
@@ -66,88 +69,111 @@ add_task(async function test_swap_protoc
   await check_autocomplete({
     search: "ftp://site",
     matches: allMatches
   });
 
   info("https://www.site matches all site");
   await check_autocomplete({
     search: "https://www.site",
-    matches: allMatches
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+    ]
   });
 
   info("https://site matches all site");
   await check_autocomplete({
     search: "https://site",
     matches: allMatches
   });
 
-  info("www.site matches all site");
+  info("www.site matches 'www.site' pages");
   await check_autocomplete({
     search: "www.site",
-    matches: allMatches
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+    ]
   });
 
-  info("w matches none of www.");
+  info("w matches 'w' pages, including 'www'");
   await check_autocomplete({
     search: "w",
-    matches: [ { uri: uri7, title: "title" },
-               { uri: uri8, title: "title" } ]
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+      { uri: uri7, title: "title" },
+      { uri: uri8, title: "title" },
+    ]
   });
 
-  info("http://w matches none of www.");
+  info("http://w matches 'w' pages, including 'www'");
   await check_autocomplete({
     search: "http://w",
-    matches: [ { uri: uri7, title: "title" },
-               { uri: uri8, title: "title" } ]
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+      { uri: uri7, title: "title" },
+      { uri: uri8, title: "title" },
+    ]
   });
 
-  info("http://w matches none of www.");
+  info("http://www.w matches nothing");
   await check_autocomplete({
     search: "http://www.w",
-    matches: [ { uri: uri7, title: "title" },
-               { uri: uri8, title: "title" } ]
-  });
-
-  info("ww matches none of www.");
-  await check_autocomplete({
-    search: "ww",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: []
   });
 
-  info("ww matches none of www.");
+  info("ww matches no 'ww' pages, including 'www'");
   await check_autocomplete({
     search: "ww",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+      { uri: uri8, title: "title" },
+    ]
   });
 
-  info("http://ww matches none of www.");
+  info("http://ww matches no 'ww' pages, including 'www'");
   await check_autocomplete({
     search: "http://ww",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+      { uri: uri8, title: "title" },
+    ]
   });
 
-  info("http://www.ww matches none of www.");
+  info("http://www.ww matches nothing");
   await check_autocomplete({
     search: "http://www.ww",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: []
   });
 
-  info("www matches none of www.");
+  info("www matches 'www' pages");
   await check_autocomplete({
     search: "www",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+      { uri: uri8, title: "title" },
+    ]
   });
 
-  info("http://www matches none of www.");
+  info("http://www matches 'www' pages");
   await check_autocomplete({
     search: "http://www",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: [
+      { uri: uri1, title: "title" },
+      { uri: uri5, title: "title" },
+      { uri: uri8, title: "title" },
+    ]
   });
 
-  info("http://www.www matches none of www.");
+  info("http://www.www matches nothing");
   await check_autocomplete({
     search: "http://www.www",
-    matches: [ { uri: uri8, title: "title" } ]
+    matches: []
   });
 
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js
@@ -2,16 +2,18 @@
  * vim:set ts=2 sw=2 sts=2 et:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var gTabRestrictChar = "%";
 
 add_task(async function test_tab_matches() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+
   let uri1 = NetUtil.newURI("http://abc.com/");
   let uri2 = NetUtil.newURI("http://xyz.net/");
   let uri3 = NetUtil.newURI("about:mozilla");
   let uri4 = NetUtil.newURI("data:text/html,test");
   let uri5 = NetUtil.newURI("http://foobar.org");
   await PlacesTestUtils.addVisits([
     { uri: uri1, title: "ABC rocks" },
     { uri: uri2, title: "xyz.net - we're better than ABC" },
--- a/toolkit/components/places/tests/unifiedcomplete/test_trimming.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_trimming.js
@@ -1,313 +1,120 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(async function test_untrimmed_secure_www() {
   info("Searching for untrimmed https://www entry");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://www.mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mo",
     autofilled: "mozilla.org/",
     completed: "https://www.mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_secure_www_path() {
   info("Searching for untrimmed https://www entry with path");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://www.mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.org/t",
     autofilled: "mozilla.org/test/",
     completed: "https://www.mozilla.org/test/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_secure() {
   info("Searching for untrimmed https:// entry");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mo",
     autofilled: "mozilla.org/",
     completed: "https://mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_secure_path() {
   info("Searching for untrimmed https:// entry with path");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.org/t",
     autofilled: "mozilla.org/test/",
     completed: "https://mozilla.org/test/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_www() {
   info("Searching for untrimmed http://www entry");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://www.mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mo",
     autofilled: "mozilla.org/",
-    completed: "www.mozilla.org/"
+    completed: "http://www.mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_www_path() {
   info("Searching for untrimmed http://www entry with path");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://www.mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.org/t",
     autofilled: "mozilla.org/test/",
     completed: "http://www.mozilla.org/test/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_ftp() {
   info("Searching for untrimmed ftp:// entry");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("ftp://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mo",
     autofilled: "mozilla.org/",
     completed: "ftp://mozilla.org/"
   });
   await cleanup();
 });
 
 add_task(async function test_untrimmed_ftp_path() {
   info("Searching for untrimmed ftp:// entry with path");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("ftp://mozilla.org/test/"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "mozilla.org/t",
     autofilled: "mozilla.org/test/",
     completed: "ftp://mozilla.org/test/"
   });
   await cleanup();
 });
 
-add_task(async function test_priority_1() {
-  info("Ensuring correct priority 1");
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("https://www.mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("https://mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_priority_2() {
-  info( "Ensuring correct priority 2");
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("https://mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_priority_3() {
-  info("Ensuring correct priority 3");
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_priority_4() {
-  info("Ensuring correct priority 4");
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.org/",
-    completed: "www.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_priority_5() {
-  info("Ensuring correct priority 5");
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("ftp://www.mozilla.org/test/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.org/",
-    completed: "ftp://mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_priority_6() {
-  info("Ensuring correct priority 6");
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("http://www.mozilla.org/test1/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://www.mozilla.org/test2/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.org/",
-    completed: "www.mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_longer_domain() {
-  info("Ensuring longer domain can't match");
-  // The .co should be preferred, but should not get the https from the .com.
-  // The .co domain must be added later to activate the trigger bug.
-  await PlacesTestUtils.addVisits([
-    { uri: NetUtil.newURI("https://mozilla.com/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://mozilla.co/"), transition: TRANSITION_TYPED },
-    { uri: NetUtil.newURI("http://mozilla.co/"), transition: TRANSITION_TYPED }
-  ]);
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "mozilla.co/",
-    completed: "mozilla.co/"
-  });
-
-  await cleanup();
-});
-
 add_task(async function test_escaped_chars() {
   info("Searching for URL with characters that are normally escaped");
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("https://www.mozilla.org/å•Š-test"),
-    transition: TRANSITION_TYPED
   });
   await check_autocomplete({
     search: "https://www.mozilla.org/å•Š-test",
     autofilled: "https://www.mozilla.org/å•Š-test",
     completed: "https://www.mozilla.org/å•Š-test"
   });
   await cleanup();
 });
-
-add_task(async function test_unsecure_secure() {
-  info("Don't return unsecure URL when searching for secure ones");
-  await PlacesTestUtils.addVisits({
-    uri: NetUtil.newURI("http://test.moz.org/test/"),
-    transition: TRANSITION_TYPED
-  });
-  await check_autocomplete({
-    search: "https://test.moz.org/t",
-    autofilled: "https://test.moz.org/test/",
-    completed: "https://test.moz.org/test/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_unsecure_secure_domain() {
-  info("Don't return unsecure domain when searching for secure ones");
-  await PlacesTestUtils.addVisits({
-    uri: NetUtil.newURI("http://test.moz.org/test/"),
-    transition: TRANSITION_TYPED
-  });
-  await check_autocomplete({
-    search: "https://test.moz",
-    autofilled: "https://test.moz.org/",
-    completed: "https://test.moz.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_untyped_www() {
-  info("Untyped is not accounted for www");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://www.moz.org/test/") });
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "moz.org/",
-    completed: "moz.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_untyped_ftp() {
-  info("Untyped is not accounted for ftp");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits({ uri: NetUtil.newURI("ftp://moz.org/test/") });
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "moz.org/",
-    completed: "moz.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_untyped_secure() {
-  info("Untyped is not accounted for https");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits({ uri: NetUtil.newURI("https://moz.org/test/") });
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "moz.org/",
-    completed: "moz.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_untyped_secure_www() {
-  info("Untyped is not accounted for https://www");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits({ uri: NetUtil.newURI("https://www.moz.org/test/") });
-  await check_autocomplete({
-    search: "mo",
-    autofilled: "moz.org/",
-    completed: "moz.org/"
-  });
-  await cleanup();
-});
deleted file mode 100644
--- a/toolkit/components/places/tests/unifiedcomplete/test_typed.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// First do searches with typed behavior forced to false, so later tests will
-// ensure autocomplete is able to dinamically switch behavior.
-
-const FAVICON_HREF = NetUtil.newURI(do_get_file("../favicons/favicon-normal16.png")).spec;
-
-add_task(async function test_domain() {
-  info("Searching for domain should autoFill it");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/"));
-  await setFaviconForPage("http://mozilla.org/link/", FAVICON_HREF);
-  await check_autocomplete({
-    search: "moz",
-    autofilled: "mozilla.org/",
-    completed: "mozilla.org/",
-    icon: "moz-anno:favicon:" + FAVICON_HREF
-  });
-  await cleanup();
-});
-
-add_task(async function test_url() {
-  info("Searching for url should autoFill it");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/"));
-  await setFaviconForPage("http://mozilla.org/link/", FAVICON_HREF);
-  await check_autocomplete({
-    search: "mozilla.org/li",
-    autofilled: "mozilla.org/link/",
-    completed: "http://mozilla.org/link/",
-    icon: "moz-anno:favicon:" + FAVICON_HREF
-  });
-  await cleanup();
-});
-
-// Now do searches with typed behavior forced to true.
-
-add_task(async function test_untyped_domain() {
-  info("Searching for non-typed domain should not autoFill it");
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/"));
-  await check_autocomplete({
-    search: "moz",
-    autofilled: "moz",
-    completed: "moz"
-  });
-  await cleanup();
-});
-
-add_task(async function test_typed_domain() {
-  info("Searching for typed domain should autoFill it");
-  await PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://mozilla.org/typed/"),
-                           transition: TRANSITION_TYPED });
-  await check_autocomplete({
-    search: "moz",
-    autofilled: "mozilla.org/",
-    completed: "mozilla.org/"
-  });
-  await cleanup();
-});
-
-add_task(async function test_untyped_url() {
-  info("Searching for non-typed url should not autoFill it");
-  await PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/"));
-  await check_autocomplete({
-    search: "mozilla.org/li",
-    autofilled: "mozilla.org/li",
-    completed: "mozilla.org/li"
-  });
-  await cleanup();
-});
-
-add_task(async function test_typed_url() {
-  info("Searching for typed url should autoFill it");
-  await PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://mozilla.org/link/"),
-                           transition: TRANSITION_TYPED });
-  await check_autocomplete({
-    search: "mozilla.org/li",
-    autofilled: "mozilla.org/link/",
-    completed: "http://mozilla.org/link/"
-  });
-  await cleanup();
-});
--- a/toolkit/components/places/tests/unifiedcomplete/test_word_boundary_search.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_word_boundary_search.js
@@ -14,16 +14,17 @@
  * make sure "can match" matches anywhere.
  */
 
 var katakana = ["\u30a8", "\u30c9"]; // E, Do
 var ideograph = ["\u4efb", "\u5929", "\u5802"]; // Nin Ten Do
 
 add_task(async function test_escape() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false);
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
 
   let uri1 = NetUtil.newURI("http://matchme/");
   let uri2 = NetUtil.newURI("http://dontmatchme/");
   let uri3 = NetUtil.newURI("http://title/1");
   let uri4 = NetUtil.newURI("http://title/2");
   let uri5 = NetUtil.newURI("http://tag/1");
   let uri6 = NetUtil.newURI("http://tag/2");
   let uri7 = NetUtil.newURI("http://crazytitle/");
--- a/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js
@@ -1,32 +1,30 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Ensure inline autocomplete doesn't return zero frecency pages.
 
-add_task(async function test_zzero_frec_domain() {
+add_task(async function test_zero_frec_domain() {
   info("Searching for zero frecency domain should not autoFill it");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/framed_link/"),
     transition: TRANSITION_FRAMED_LINK
   });
   await check_autocomplete({
     search: "moz",
     autofilled: "moz",
     completed:  "moz"
   });
   await cleanup();
 });
 
-add_task(async function test_zzero_frec_url() {
+add_task(async function test_zero_frec_url() {
   info("Searching for zero frecency url should not autoFill it");
-  Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false);
   await PlacesTestUtils.addVisits({
     uri: NetUtil.newURI("http://mozilla.org/framed_link/"),
     transition: TRANSITION_FRAMED_LINK
   });
   await check_autocomplete({
     search: "mozilla.org/f",
     autofilled: "mozilla.org/f",
     completed:  "mozilla.org/f"
--- a/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini
+++ b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini
@@ -1,25 +1,28 @@
 [DEFAULT]
 head = head_autocomplete.js
 skip-if = toolkit == 'android'
 firefox-appdir = browser
 support-files =
   data/engine-rel-searchform.xml
   data/engine-suggestions.xml
   !/toolkit/components/places/tests/favicons/favicon-normal16.png
+  autofill_tasks.js
 
 [test_416211.js]
 [test_416214.js]
 [test_417798.js]
 [test_418257.js]
 [test_422277.js]
 [test_autocomplete_functional.js]
 [test_autocomplete_stopSearch_no_throw.js]
-[test_autofill_default_behavior.js]
+[test_autofill_origins.js]
+[test_autofill_search_engines.js]
+[test_autofill_urls.js]
 [test_avoid_middle_complete.js]
 [test_avoid_stripping_to_empty_tokens.js]
 [test_casing.js]
 [test_do_not_trim.js]
 [test_download_embed_bookmarks.js]
 [test_dupe_urls.js]
 [test_empty_search.js]
 [test_enabled.js]
@@ -42,12 +45,11 @@ skip-if = !sync
 [test_search_engine_current.js]
 [test_search_engine_host.js]
 [test_search_engine_restyle.js]
 [test_search_suggestions.js]
 [test_special_search.js]
 [test_swap_protocol.js]
 [test_tab_matches.js]
 [test_trimming.js]
-[test_typed.js]
 [test_visit_url.js]
 [test_word_boundary_search.js]
 [test_zero_frecency.js]
--- a/toolkit/components/places/tests/unit/test_adaptive_bug527311.js
+++ b/toolkit/components/places/tests/unit/test_adaptive_bug527311.js
@@ -102,16 +102,23 @@ function addAdaptiveFeedback(aUrl, aSear
       searchString: aSearch
     };
 
     Services.obs.notifyObservers(thing, "autocomplete-will-enter-text");
   });
 }
 
 
+add_task(function init() {
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
+  registerCleanupFunction(() => {
+    Services.prefs.clearUserPref("browser.urlbar.autoFill");
+  });
+});
+
 add_task(async function test_adaptive_search_specific() {
   // Add a bookmark to our url.
   await PlacesUtils.bookmarks.insert({
     parentGuid: PlacesUtils.bookmarks.unfiledGuid,
     title: "test_book",
     url: TEST_URL,
   });
 
deleted file mode 100644
--- a/toolkit/components/places/tests/unit/test_hosts_triggers.js
+++ /dev/null
@@ -1,377 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * This file tests the validity of various triggers that add remove hosts from moz_hosts
- */
-
-XPCOMUtils.defineLazyServiceGetter(this, "gHistory",
-                                   "@mozilla.org/browser/history;1",
-                                   "mozIAsyncHistory");
-
-// add some visits and remove them, add a bookmark,
-// change its uri, then remove it, and
-// for each change check that moz_hosts has correctly been updated.
-
-function isHostInMozPlaces(aURI) {
-  let stmt = DBConn().createStatement(
-    `SELECT url
-       FROM moz_places
-       WHERE url_hash = hash(:host) AND url = :host`
-  );
-  let result = false;
-  stmt.params.host = aURI.spec;
-  while (stmt.executeStep()) {
-    if (stmt.row.url == aURI.spec) {
-      result = true;
-      break;
-    }
-  }
-  stmt.finalize();
-  return result;
-}
-
-function checkHostInMozHosts(aURI, aTyped, aPrefix, aShouldBePresent = true) {
-  if (typeof aURI == "string") {
-    aURI = new URL(aURI);
-  }
-  let stmt = DBConn().createStatement(
-    `SELECT host, typed, prefix
-       FROM moz_hosts
-       WHERE host = fixup_url(:host)
-       AND frecency NOTNULL`
-  );
-  let result;
-  stmt.params.host = aURI.host;
-  if (stmt.executeStep()) {
-    result = {typed: stmt.row.typed, prefix: stmt.row.prefix};
-  }
-  stmt.finalize();
-
-  if (aShouldBePresent) {
-    Assert.ok(result, "Result should be defined.");
-    Assert.equal(result.typed, aTyped, "The typed field should match.");
-    Assert.equal(result.prefix, aPrefix, "The prefix field should match.");
-  } else {
-    Assert.strictEqual(result, undefined);
-  }
-}
-
-function checkHostNotInMozHosts(aURI, aTyped, aPrefix) {
-  checkHostInMozHosts(aURI, aTyped, aPrefix, false);
-}
-
-var urls = [{uri: NetUtil.newURI("http://visit1.mozilla.org"),
-             expected: "visit1.mozilla.org",
-             typed: 0,
-             prefix: null
-            },
-            {uri: NetUtil.newURI("http://visit2.mozilla.org"),
-             expected: "visit2.mozilla.org",
-             typed: 0,
-             prefix: null
-            },
-            {uri: NetUtil.newURI("http://www.foo.mozilla.org"),
-             expected: "foo.mozilla.org",
-             typed: 1,
-             prefix: "www."
-            },
-           ];
-
-const NEW_URL = "http://different.mozilla.org/";
-
-add_task(async function test_moz_hosts_update() {
-  let places = [];
-  urls.forEach(function(url) {
-    let place = { uri: url.uri,
-                  title: "test for " + url.uri.spec,
-                  transition: url.typed ? TRANSITION_TYPED : undefined };
-    places.push(place);
-  });
-
-  await PlacesTestUtils.addVisits(places);
-
-  checkHostInMozHosts(urls[0].uri, urls[0].typed, urls[0].prefix);
-  checkHostInMozHosts(urls[1].uri, urls[1].typed, urls[1].prefix);
-  checkHostInMozHosts(urls[2].uri, urls[2].typed, urls[2].prefix);
-});
-
-add_task(async function test_remove_places() {
-  await PlacesUtils.history.remove(urls.map(x => x.uri));
-
-  for (let idx in urls) {
-    checkHostNotInMozHosts(urls[idx].uri, urls[idx].typed, urls[idx].prefix);
-  }
-});
-
-add_task(async function test_bookmark_changes() {
-  let testUri = NetUtil.newURI("http://test.mozilla.org");
-
-  let bookmark = await PlacesUtils.bookmarks.insert({
-    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
-    url: testUri,
-    title: "bookmark title",
-  });
-
-  Assert.ok(isHostInMozPlaces(testUri));
-
-  // Change the hostname
-  await PlacesUtils.bookmarks.update({
-    guid: bookmark.guid,
-    url: NEW_URL,
-  });
-
-  await PlacesUtils.history.clear();
-
-  let newUri = NetUtil.newURI(NEW_URL);
-  Assert.ok(isHostInMozPlaces(newUri));
-  checkHostInMozHosts(newUri, false, null);
-  checkHostNotInMozHosts(NetUtil.newURI("http://test.mozilla.org"), false, null);
-});
-
-add_task(async function test_bookmark_removal() {
-  // Get the last bookmark.
-  let unfiledBookmarksRoot =
-    await PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
-  let itemGuid =
-    unfiledBookmarksRoot.getChild(unfiledBookmarksRoot.childCount - 1).bookmarkGuid;
-
-  await PlacesUtils.bookmarks.remove(itemGuid);
-  await PlacesUtils.history.clear();
-
-  checkHostNotInMozHosts(Services.io.newURI(NEW_URL), false, null);
-});
-
-add_task(async function test_moz_hosts_typed_update() {
-  const TEST_URI = NetUtil.newURI("http://typed.mozilla.com");
-  let places = [{ uri: TEST_URI,
-                  title: "test for " + TEST_URI.spec
-                },
-                { uri: TEST_URI,
-                  title: "test for " + TEST_URI.spec,
-                  transition: TRANSITION_TYPED
-                }];
-
-  await PlacesTestUtils.addVisits(places);
-
-  checkHostInMozHosts(TEST_URI, true, null);
-  await PlacesUtils.history.clear();
-});
-
-add_task(async function test_moz_hosts_www_remove() {
-  async function test_removal(aURIToRemove, aURIToKeep, aCallback) {
-    let places = [{ uri: aURIToRemove,
-                    title: "test for " + aURIToRemove.spec,
-                    transition: TRANSITION_TYPED
-                  },
-                  { uri: aURIToKeep,
-                    title: "test for " + aURIToKeep.spec,
-                    transition: TRANSITION_TYPED
-                  }];
-
-    await PlacesTestUtils.addVisits(places);
-    print("removing " + aURIToRemove.spec + " keeping " + aURIToKeep);
-    dump_table("moz_hosts");
-    dump_table("moz_places");
-    await PlacesUtils.history.remove(aURIToRemove);
-    let prefix = /www/.test(aURIToKeep.spec) ? "www." : null;
-    dump_table("moz_hosts");
-    dump_table("moz_places");
-    checkHostInMozHosts(aURIToKeep, true, prefix);
-  }
-
-  const TEST_URI = NetUtil.newURI("http://rem.mozilla.com");
-  const TEST_WWW_URI = NetUtil.newURI("http://www.rem.mozilla.com");
-  await test_removal(TEST_URI, TEST_WWW_URI);
-  await test_removal(TEST_WWW_URI, TEST_URI);
-  await PlacesUtils.history.clear();
-});
-
-add_task(async function test_moz_hosts_ftp_matchall() {
-  const TEST_URI_1 = NetUtil.newURI("ftp://www.mozilla.com/");
-  const TEST_URI_2 = NetUtil.newURI("ftp://mozilla.com/");
-
-  await PlacesTestUtils.addVisits([
-    { uri: TEST_URI_1, transition: TRANSITION_TYPED },
-    { uri: TEST_URI_2, transition: TRANSITION_TYPED }
-  ]);
-
-  checkHostInMozHosts(TEST_URI_1, true, "ftp://");
-});
-
-add_task(async function test_moz_hosts_ftp_not_matchall() {
-  const TEST_URI_1 = NetUtil.newURI("http://mozilla.com/");
-  const TEST_URI_2 = NetUtil.newURI("ftp://mozilla.com/");
-
-  await PlacesTestUtils.addVisits([
-    { uri: TEST_URI_1, transition: TRANSITION_TYPED },
-    { uri: TEST_URI_2, transition: TRANSITION_TYPED }
-  ]);
-
-  checkHostInMozHosts(TEST_URI_1, true, null);
-});
-
-add_task(async function test_moz_hosts_update_2() {
-  // Check that updating trigger takes into account prefixes for different
-  // rev_hosts.
-  const TEST_URI_1 = NetUtil.newURI("https://www.google.it/");
-  const TEST_URI_2 = NetUtil.newURI("https://google.it/");
-  let places = [{ uri: TEST_URI_1,
-                  transition: TRANSITION_TYPED
-                },
-                { uri: TEST_URI_2
-                }];
-  await PlacesTestUtils.addVisits(places);
-
-  checkHostInMozHosts(TEST_URI_1, true, "https://www.");
-});
-
-function getTestSection(baseURL1, baseURL2, baseURL2Prefix, extra) {
-  let extraStr = "";
-  let expectedSimplePrefix = null;
-  let expectedUpgradePrefix = baseURL2Prefix;
-  if (extra) {
-    extraStr = ` (${extra})`;
-    expectedSimplePrefix = `${extra}.`;
-    expectedUpgradePrefix = `${baseURL2Prefix}${extra}.`;
-  }
-  return [{
-    title: `Test simple url${extraStr}`,
-    visits: [{ uri: baseURL1, transition: TRANSITION_TYPED }],
-    expect: [baseURL1, true, expectedSimplePrefix]
-  }, {
-    title: `Test upgrade url${extraStr}`,
-    visits: [{ uri: baseURL2, transition: TRANSITION_TYPED }],
-    expect: [baseURL2, true, expectedUpgradePrefix]
-  }, {
-    title: `Test remove simple completely${extraStr}`,
-    remove: baseURL1,
-    expect: [baseURL2, true, expectedUpgradePrefix]
-  }, {
-    title: `Test add more visits${extraStr}`,
-    visits: [
-      { uri: baseURL2, transition: TRANSITION_TYPED },
-      { uri: baseURL1, transition: TRANSITION_TYPED },
-    ],
-    expect: [baseURL2, true, expectedUpgradePrefix]
-  }, {
-    title: `Test remove upgrade url${extraStr}`,
-    remove: baseURL2,
-    expect: [baseURL2, true, expectedSimplePrefix]
-  }];
-}
-
-const hostsUpdateTests = [{
-  title: "Upgrade Secure/Downgrade Insecure",
-  tests: getTestSection("http://example.com", "https://example.com", "https://")
-}, {
-  title: "Upgrade Secure/Downgrade Insecure (www)",
-  tests: getTestSection("http://www.example1.com", "https://www.example1.com", "https://", "www")
-}, {
-  title: "Upgrade Secure/Downgrade non-www to www",
-  tests: getTestSection("http://example3.com", "http://www.example3.com", "www.")
-}, {
-  title: "Switch to/from ftp",
-  tests: [{
-    title: `Test normal url`,
-    visits: [{ uri: "http://example4.com", transition: TRANSITION_TYPED }],
-    expect: ["http://example4.com", true, null]
-  }, {
-    title: `Test switch to ftp`,
-    visits: [{ uri: "ftp://example4.com", transition: TRANSITION_TYPED }],
-    // ftp is only switched to if all pages are ftp://
-    remove: ["http://example4.com"],
-    expect: ["ftp://example4.com", true, "ftp://"]
-  }, {
-    title: `Test visit http`,
-    visits: [{ uri: "http://example4.com", transition: TRANSITION_TYPED }],
-    expect: ["ftp://example4.com", true, null]
-  }]
-}, {
-  title: "Multiple URLs for source",
-  tests: [{
-    title: `Test simple insecure`,
-    visits: [{ uri: "http://example2.com", transition: TRANSITION_TYPED }],
-    expect: ["http://example2.com", true, null]
-  }, {
-    title: `Test upgrade secure`,
-    visits: [{ uri: "https://example2.com", transition: TRANSITION_TYPED }],
-    expect: ["https://example2.com", true, "https://"]
-  }, {
-    title: `Test extra insecure visit`,
-    visits: [{ uri: "http://example2.com/fake", transition: TRANSITION_TYPED }],
-    expect: ["https://example2.com", true, null]
-  }, {
-    title: `Test extra secure visits`,
-    visits: [
-      { uri: "https://example2.com/foo", transition: TRANSITION_TYPED },
-      { uri: "https://example2.com/bar", transition: TRANSITION_TYPED },
-    ],
-    expect: ["https://example2.com", true, "https://"]
-  }, {
-    title: `Test remove secure`,
-    remove: ["https://example2.com", "https://example2.com/foo", "https://example2.com/bar"],
-    expect: ["https://example2.com", true, null]
-  }]
-}, {
-  title: "Test upgrade tree",
-  tests: [{
-    title: `Add ftp`,
-    visits: [{ uri: "ftp://example5.com", transition: TRANSITION_TYPED }],
-    expect: ["http://example5.com", true, "ftp://"]
-  }, {
-    title: `Add basic http`,
-    visits: [{ uri: "http://example5.com", transition: TRANSITION_TYPED }],
-    expect: ["http://example5.com", true, null]
-  }, {
-    title: `Add basic www`,
-    visits: [
-      // Add multiples to exceed the average.
-      { uri: "http://www.example5.com", transition: TRANSITION_TYPED },
-      { uri: "http://www.example5.com/past", transition: TRANSITION_TYPED }
-    ],
-    expect: ["http://example5.com", true, "www."]
-  }, {
-    title: `Add https`,
-    visits: [
-      // Add multiples to exceed the average.
-      { uri: "https://example5.com", transition: TRANSITION_TYPED },
-      { uri: "https://example5.com/past", transition: TRANSITION_TYPED },
-      { uri: "https://example5.com/mak", transition: TRANSITION_TYPED },
-      { uri: "https://example5.com/standard8", transition: TRANSITION_TYPED }
-    ],
-    expect: ["https://example5.com", true, "https://"]
-  }, {
-    title: `Add https www`,
-    visits: [
-      // Add multiples to exceed the average.
-      { uri: "https://www.example5.com", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/quantum", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/photon", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/dash", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/flow", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/persona", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/ff_fx", transition: TRANSITION_TYPED },
-      { uri: "https://www.example5.com/search", transition: TRANSITION_TYPED }
-    ],
-    expect: ["https://example5.com", true, "https://www."]
-  }]
-}];
-
-add_task(async function test_moz_hosts_update() {
-  for (const section of hostsUpdateTests) {
-    info(section.title);
-
-    for (const test of section.tests) {
-      info(test.title);
-
-      if ("visits" in test) {
-        await PlacesTestUtils.addVisits(test.visits);
-      }
-      if ("remove" in test) {
-        await PlacesUtils.history.remove(test.remove);
-      }
-      checkHostInMozHosts(test.expect[0], test.expect[1], test.expect[2]);
-    }
-  }
-});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_origins.js
@@ -0,0 +1,417 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Makes sure the moz_origins table is updated correctly.
+
+// Comprehensive prefix and origin parsing test.
+add_task(async function parsing() {
+  let prefixes = [
+    "http://",
+    "https://",
+    "ftp://",
+    "foo://",
+    "bar:",
+  ];
+
+  let userinfos = [
+    "",
+    "user:pass@",
+    "user:pass:word@",
+    "user:@",
+  ];
+
+  let ports = [
+    "",
+    ":8888",
+  ];
+
+  let paths = [
+    "",
+
+    "/",
+    "/1",
+    "/1/2",
+
+    "?",
+    "?1",
+    "#",
+    "#1",
+
+    "/?",
+    "/1?",
+    "/?1",
+    "/1?2",
+
+    "/#",
+    "/1#",
+    "/#1",
+    "/1#2",
+
+    "/?#",
+    "/1?#",
+    "/?1#",
+    "/?#1",
+    "/1?2#",
+    "/1?#2",
+    "/?1#2",
+  ];
+
+  for (let userinfo of userinfos) {
+    for (let port of ports) {
+      for (let path of paths) {
+        info(`Testing userinfo='${userinfo}' port='${port}' path='${path}'`);
+        let prefixAndHostPorts = prefixes.map(prefix =>
+          [prefix, "example.com" + port]
+        );
+        let uris = prefixAndHostPorts.map(([prefix, hostPort]) =>
+          prefix + userinfo + hostPort + path
+        );
+
+        await PlacesTestUtils.addVisits(uris.map(uri => ({ uri })));
+        await checkDB(prefixAndHostPorts);
+
+        // Remove each URI, one at a time, and make sure the remaining origins
+        // in the database are correct.
+        for (let i = 0; i < uris.length; i++) {
+          await PlacesUtils.history.remove(uris[i]);
+          await checkDB(prefixAndHostPorts.slice(i + 1,
+                                                 prefixAndHostPorts.length));
+        }
+        await cleanUp();
+      }
+    }
+  }
+});
+
+
+// Makes sure URIs with the same TLD but different www subdomains are recognized
+// as different origins.  Makes sure removing one doesn't remove the others.
+add_task(async function www1() {
+  await PlacesTestUtils.addVisits([
+    { uri: "http://example.com/" },
+    { uri: "http://www.example.com/" },
+    { uri: "http://www.www.example.com/" },
+  ]);
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com/");
+  await checkDB([
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://www.example.com/");
+  await checkDB([
+    ["http://", "www.www.example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://www.www.example.com/");
+  await checkDB([
+  ]);
+  await cleanUp();
+});
+
+
+// Same as www1, but removes URIs in a different order.
+add_task(async function www2() {
+  await PlacesTestUtils.addVisits([
+    { uri: "http://example.com/" },
+    { uri: "http://www.example.com/" },
+    { uri: "http://www.www.example.com/" },
+  ]);
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://www.www.example.com/");
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://www.example.com/");
+  await checkDB([
+    ["http://", "example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com/");
+  await checkDB([
+  ]);
+  await cleanUp();
+});
+
+
+// Makes sure removing an origin without a port doesn't remove the same host
+// with a port.
+add_task(async function ports1() {
+  await PlacesTestUtils.addVisits([
+    { uri: "http://example.com/" },
+    { uri: "http://example.com:8888/" },
+  ]);
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com/");
+  await checkDB([
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com:8888/");
+  await checkDB([
+  ]);
+  await cleanUp();
+});
+
+
+// Makes sure removing an origin with a port doesn't remove the same host
+// without a port.
+add_task(async function ports2() {
+  await PlacesTestUtils.addVisits([
+    { uri: "http://example.com/" },
+    { uri: "http://example.com:8888/" },
+  ]);
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com:8888/");
+  await checkDB([
+    ["http://", "example.com"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com/");
+  await checkDB([
+  ]);
+  await cleanUp();
+});
+
+
+// Makes sure multiple URIs with the same origin don't create duplicate origins.
+add_task(async function duplicates() {
+  await PlacesTestUtils.addVisits([
+    { uri: "http://example.com/" },
+    { uri: "http://www.example.com/" },
+    { uri: "http://www.www.example.com/" },
+    { uri: "https://example.com/" },
+    { uri: "ftp://example.com/" },
+    { uri: "foo://example.com/" },
+    { uri: "bar:example.com/" },
+    { uri: "http://example.com:8888/" },
+
+    { uri: "http://example.com/dupe" },
+    { uri: "http://www.example.com/dupe" },
+    { uri: "http://www.www.example.com/dupe" },
+    { uri: "https://example.com/dupe" },
+    { uri: "ftp://example.com/dupe" },
+    { uri: "foo://example.com/dupe" },
+    { uri: "bar:example.com/dupe" },
+    { uri: "http://example.com:8888/dupe" },
+  ]);
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("http://example.com/");
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com/dupe");
+  await checkDB([
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("http://www.example.com/");
+  await checkDB([
+    ["http://", "www.example.com"],
+    ["http://", "www.www.example.com"],
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://www.example.com/dupe");
+  await checkDB([
+    ["http://", "www.www.example.com"],
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("http://www.www.example.com/");
+  await checkDB([
+    ["http://", "www.www.example.com"],
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://www.www.example.com/dupe");
+  await checkDB([
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("https://example.com/");
+  await checkDB([
+    ["https://", "example.com"],
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("https://example.com/dupe");
+  await checkDB([
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("ftp://example.com/");
+  await checkDB([
+    ["ftp://", "example.com"],
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("ftp://example.com/dupe");
+  await checkDB([
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("foo://example.com/");
+  await checkDB([
+    ["foo://", "example.com"],
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("foo://example.com/dupe");
+  await checkDB([
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("bar:example.com/");
+  await checkDB([
+    ["bar:", "example.com"],
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("bar:example.com/dupe");
+  await checkDB([
+    ["http://", "example.com:8888"],
+  ]);
+
+  await PlacesUtils.history.remove("http://example.com:8888/");
+  await checkDB([
+    ["http://", "example.com:8888"],
+  ]);
+  await PlacesUtils.history.remove("http://example.com:8888/dupe");
+  await checkDB([
+  ]);
+
+  await cleanUp();
+});
+
+
+// Makes sure adding and removing bookmarks creates origins.
+add_task(async function addRemoveBookmarks() {
+  let bookmarks = [];
+  let urls = [
+    "http://example.com/",
+    "http://www.example.com/",
+  ];
+  for (let url of urls) {
+    bookmarks.push(await PlacesUtils.bookmarks.insert({
+      url,
+      parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    }));
+  }
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+  ]);
+  await PlacesUtils.bookmarks.remove(bookmarks[0]);
+  await PlacesUtils.history.clear();
+  await checkDB([
+    ["http://", "www.example.com"],
+  ]);
+  await PlacesUtils.bookmarks.remove(bookmarks[1]);
+  await PlacesUtils.history.clear();
+  await checkDB([
+  ]);
+  await cleanUp();
+});
+
+
+// Makes sure changing bookmarks also changes the corresponding origins.
+add_task(async function changeBookmarks() {
+  let bookmarks = [];
+  let urls = [
+    "http://example.com/",
+    "http://www.example.com/",
+  ];
+  for (let url of urls) {
+    bookmarks.push(await PlacesUtils.bookmarks.insert({
+      url,
+      parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    }));
+  }
+  await checkDB([
+    ["http://", "example.com"],
+    ["http://", "www.example.com"],
+  ]);
+  await PlacesUtils.bookmarks.update({
+    url: "http://www.example.com/",
+    guid: bookmarks[0].guid,
+  });
+  await PlacesUtils.history.clear();
+  await checkDB([
+    ["http://", "www.example.com"],
+  ]);
+  await cleanUp();
+});
+
+
+async function checkDB(expectedOrigins) {
+  let db = await PlacesUtils.promiseDBConnection();
+  let rows = await db.execute(`
+    SELECT prefix, host
+    FROM moz_origins
+    ORDER BY id ASC
+  `);
+  let actual = rows.map(r => [r.getString(0), r.getString(1)]);
+  Assert.deepEqual(actual, expectedOrigins);
+}
+
+async function cleanUp() {
+  await PlacesUtils.bookmarks.eraseEverything();
+  await PlacesUtils.history.clear();
+}
--- a/toolkit/components/places/tests/unit/test_preventive_maintenance.js
+++ b/toolkit/components/places/tests/unit/test_preventive_maintenance.js
@@ -47,17 +47,17 @@ function addPlace(aUrl, aFavicon, aGuid 
   let href = new URL(aUrl || "http://www.mozilla.org").href;
   let stmt = mDBConn.createStatement(
     "INSERT INTO moz_places (url, url_hash, guid) VALUES (:url, hash(:url), :guid)");
   stmt.params.url = href;
   stmt.params.guid = aGuid;
   stmt.execute();
   stmt.finalize();
   stmt = mDBConn.createStatement(
-    "DELETE FROM moz_updatehostsinsert_temp");
+    "DELETE FROM moz_updateoriginsinsert_temp");
   stmt.execute();
   stmt.finalize();
   let id = mDBConn.lastInsertRowID;
   if (aFavicon) {
     stmt = mDBConn.createStatement(
       "INSERT INTO moz_pages_w_icons (page_url, page_url_hash) VALUES (:url, hash(:url))");
     stmt.params.url = href;
     stmt.execute();
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_sql_function_origin.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests the origin-related SQL functions, which are:
+// * get_host_and_port
+// * get_prefix
+// * strip_prefix_and_userinfo
+
+add_task(async function test() {
+  let sets = [
+    ["http:"],
+    ["", "//"],
+    ["", "user@", "user:@", "user:pass@", "user:pass:word@"],
+    ["example.com"],
+    ["", ":8888"],
+    ["", "/", "/foo"],
+    ["", "?", "?bar"],
+    ["", "#", "#baz"],
+  ];
+  let db = await PlacesUtils.promiseDBConnection();
+  for (let parts of permute(sets)) {
+    let spec = parts.join("");
+    let funcs = {
+      "get_prefix": parts.slice(0, 2).join(""),
+      "get_host_and_port": parts.slice(3, 5).join(""),
+      "strip_prefix_and_userinfo": parts.slice(3).join(""),
+    };
+    for (let [func, expectedValue] of Object.entries(funcs)) {
+      let rows = await db.execute(`
+        SELECT ${func}("${spec}");
+      `);
+      let value = rows[0].getString(0);
+      Assert.equal(value, expectedValue, `function=${func} spec="${spec}"`);
+    }
+  }
+});
+
+function permute(sets = []) {
+  if (!sets.length) {
+    return [[]];
+  }
+  let firstSet = sets[0];
+  let otherSets = sets.slice(1);
+  let permutedSequences = [];
+  let otherPermutedSequences = permute(otherSets);
+  for (let other of otherPermutedSequences) {
+    for (let value of firstSet) {
+      permutedSequences.push([value].concat(other));
+    }
+  }
+  return permutedSequences;
+}
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -72,17 +72,16 @@ skip-if = (os == "win" && os_version == 
 [test_frecency_zero_updated.js]
 [test_getChildIndex.js]
 [test_hash.js]
 [test_history.js]
 [test_history_clear.js]
 [test_history_notifications.js]
 [test_history_observer.js]
 [test_history_sidebar.js]
-[test_hosts_triggers.js]
 [test_import_mobile_bookmarks.js]
 [test_isPageInDB.js]
 [test_isURIVisited.js]
 [test_isvisited.js]
 [test_keywords.js]
 [test_lastModified.js]
 [test_markpageas.js]
 [test_metadata.js]
@@ -90,29 +89,31 @@ skip-if = (os == "win" && os_version == 
 support-files = missingBuiltIn.sqlite
 [test_missing_root_folder.js]
 support-files = noRoot.sqlite
 [test_mozIAsyncLivemarks.js]
 [test_multi_word_tags.js]
 [test_nsINavHistoryViewer.js]
 [test_null_interfaces.js]
 [test_onItemChanged_tags.js]
+[test_origins.js]
 [test_pageGuid_bookmarkGuid.js]
 [test_frecency_observers.js]
 [test_placeURIs.js]
 [test_PlacesUtils_annotations.js]
 [test_PlacesUtils_invalidateCachedGuidFor.js]
 [test_PlacesUtils_isRootItem.js]
 [test_preventive_maintenance.js]
 [test_preventive_maintenance_checkAndFixDatabase.js]
 [test_preventive_maintenance_runTasks.js]
 [test_promiseBookmarksTree.js]
 [test_resolveNullBookmarkTitles.js]
 [test_result_sort.js]
 [test_resultsAsVisit_details.js]
+[test_sql_function_origin.js]
 [test_sql_guid_functions.js]
 [test_tag_autocomplete_search.js]
 [test_tagging.js]
 [test_telemetry.js]
 [test_update_frecency_after_delete.js]
 [test_utils_backups_create.js]
 [test_utils_getURLsForContainerNode.js]
 [test_utils_setAnnotationsForItem.js]
--- a/toolkit/components/search/tests/xpcshell/test_resultDomain.js
+++ b/toolkit/components/search/tests/xpcshell/test_resultDomain.js
@@ -22,10 +22,10 @@ add_task(async function test_resultDomai
   ]);
 
   Assert.equal(engine1.getResultDomain(), "google.com");
   Assert.equal(engine1.getResultDomain("text/html"), "google.com");
   Assert.equal(engine1.getResultDomain("application/x-moz-default-purpose"),
                "purpose.google.com");
   Assert.equal(engine1.getResultDomain("fake-response-type"), "");
   Assert.equal(engine2.getResultDomain(), "duckduckgo.com");
-  Assert.equal(engine3.getResultDomain(), "bacon.moz");
+  Assert.equal(engine3.getResultDomain(), "www.bacon.moz");
 });