Bug 1617797 - Fix searching across all address books. r=mkmelin (via chat)
authorGeoff Lankow <geoff@darktrojan.net>
Wed, 26 Feb 2020 12:14:52 +1300
changeset 37433 2bccccc84b8cc201327efd26dcd89226b2e727c6
parent 37432 560479c08fef0a1657c7d7ceea382a469ff909c1
child 37434 c2a3a11627221e0056a479b1dd125e37e6e815fa
push id2566
push userclokep@gmail.com
push dateMon, 09 Mar 2020 19:20:31 +0000
treeherdercomm-beta@a352facfa0a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1617797
Bug 1617797 - Fix searching across all address books. r=mkmelin (via chat) When the concept of a root address book was removed, we lost a way to send the search URI to the tree view.
mail/components/addrbook/test/browser/browser.ini
mail/components/addrbook/test/browser/browser_search.js
mailnews/addrbook/content/abResultsPane.js
mailnews/addrbook/src/nsAbView.cpp
--- a/mail/components/addrbook/test/browser/browser.ini
+++ b/mail/components/addrbook/test/browser/browser.ini
@@ -9,8 +9,9 @@ prefs =
   mail.winsearch.firstRunDone=true
   mailnews.start_page.override_url=about:blank
   mailnews.start_page.url=about:blank
 subsuite = thunderbird
 
 [browser_ldap_search.js]
 support-files = ../../../../../mailnews/addrbook/test/unit/data/ldap_contacts.json
 [browser_mailing_lists.js]
+[browser_search.js]
new file mode 100644
--- /dev/null
+++ b/mail/components/addrbook/test/browser/browser_search.js
@@ -0,0 +1,148 @@
+/* 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 { mailTestUtils } = ChromeUtils.import(
+  "resource://testing-common/mailnews/MailTestUtils.jsm"
+);
+const { toXPCOMArray } = ChromeUtils.import(
+  "resource:///modules/iteratorUtils.jsm"
+);
+
+add_task(async () => {
+  function doSearch(searchString, ...expectedCards) {
+    return new Promise(resolve => {
+      abWindow.addEventListener(
+        "viewchange",
+        function onCountChange() {
+          checkRows(...expectedCards);
+          resolve();
+        },
+        { once: true }
+      );
+      EventUtils.synthesizeMouseAtCenter(searchBox, {}, abWindow);
+      if (searchString) {
+        EventUtils.synthesizeKey("a", { accelKey: true }, abWindow);
+        EventUtils.sendString(searchString, abWindow);
+        EventUtils.synthesizeKey("VK_RETURN", {}, abWindow);
+      } else {
+        EventUtils.synthesizeKey("VK_ESCAPE", {}, abWindow);
+      }
+    });
+  }
+
+  function checkRows(...expectedCards) {
+    is(resultsTree.view.rowCount, expectedCards.length, "rowCount correct");
+    for (let i = 0; i < expectedCards.length; i++) {
+      is(
+        resultsTree.view.getCardFromRow(i).displayName,
+        expectedCards[i].displayName,
+        `row ${i} has the right contact`
+      );
+    }
+  }
+
+  let personalBook = MailServices.ab.getDirectoryFromId("ldap_2.servers.pab");
+  let historyBook = MailServices.ab.getDirectoryFromId(
+    "ldap_2.servers.history"
+  );
+
+  let cards = {};
+  let cardsToRemove = {
+    personal: [],
+    history: [],
+  };
+  for (let name of ["daniel", "jonathan", "nathan"]) {
+    let card = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(
+      Ci.nsIAbCard
+    );
+    card.displayName = name;
+
+    card = personalBook.addCard(card);
+    cards[name] = card;
+    cardsToRemove.personal.push(card);
+  }
+  for (let name of ["danielle", "katherine", "natalie", "susanah"]) {
+    let card = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(
+      Ci.nsIAbCard
+    );
+    card.displayName = name;
+
+    card = historyBook.addCard(card);
+    cards[name] = card;
+    cardsToRemove.history.push(card);
+  }
+
+  let abWindow = await openAddressBookWindow();
+
+  registerCleanupFunction(() => {
+    abWindow.close();
+    personalBook.deleteCards(
+      toXPCOMArray(cardsToRemove.personal, Ci.nsIMutableArray)
+    );
+    historyBook.deleteCards(
+      toXPCOMArray(cardsToRemove.history, Ci.nsIMutableArray)
+    );
+  });
+
+  let abDocument = abWindow.document;
+  let dirTree = abDocument.getElementById("dirTree");
+  let resultsTree = abDocument.getElementById("abResultsTree");
+  let searchBox = abDocument.getElementById("peopleSearchInput");
+
+  // All address books.
+
+  checkRows(
+    cards.daniel,
+    cards.danielle,
+    cards.jonathan,
+    cards.katherine,
+    cards.natalie,
+    cards.nathan,
+    cards.susanah
+  );
+
+  // Personal address book.
+
+  is(dirTree.view.getCellText(1, dirTree.columns[0]), "Personal Address Book");
+  mailTestUtils.treeClick(EventUtils, abWindow, dirTree, 1, 0, {});
+  checkRows(cards.daniel, cards.jonathan, cards.nathan);
+
+  await doSearch("daniel", cards.daniel);
+  await doSearch("nathan", cards.jonathan, cards.nathan);
+
+  // History address book.
+
+  is(dirTree.view.getCellText(2, dirTree.columns[0]), "Collected Addresses");
+  mailTestUtils.treeClick(EventUtils, abWindow, dirTree, 2, 0, {});
+  checkRows(cards.danielle, cards.katherine, cards.natalie, cards.susanah);
+
+  await doSearch("daniel", cards.danielle);
+  await doSearch("nathan");
+
+  // All address books.
+
+  mailTestUtils.treeClick(EventUtils, abWindow, dirTree, 0, 0, {});
+  checkRows(
+    cards.daniel,
+    cards.danielle,
+    cards.jonathan,
+    cards.katherine,
+    cards.natalie,
+    cards.nathan,
+    cards.susanah
+  );
+
+  await doSearch("daniel", cards.daniel, cards.danielle);
+  await doSearch("nathan", cards.jonathan, cards.nathan);
+  await doSearch(
+    null,
+    cards.daniel,
+    cards.danielle,
+    cards.jonathan,
+    cards.katherine,
+    cards.natalie,
+    cards.nathan,
+    cards.susanah
+  );
+});
--- a/mailnews/addrbook/content/abResultsPane.js
+++ b/mailnews/addrbook/content/abResultsPane.js
@@ -71,31 +71,43 @@ function SetAbView(aURI) {
     }
     var sortColumnNode = document.getElementById(sortColumn);
     if (sortColumnNode && sortColumnNode.hasAttribute("sortDirection")) {
       sortDirection = sortColumnNode.getAttribute("sortDirection");
     }
   }
 
   var directory = GetDirectoryFromURI(aURI);
+  if (!directory && aURI.startsWith("moz-abdirectory://?")) {
+    // This is an obsolete reference to the root directory, which isn't a thing
+    // any more. Fortunately all we need is a way to get the URI to gAbView, so
+    // we can pretend we have a real directory.
+    directory = {
+      QueryInterface: ChromeUtils.generateQI([Ci.nsIAbDirectory]),
+      get URI() {
+        return aURI;
+      },
+    };
+  }
 
   if (!gAbView) {
     gAbView = Cc["@mozilla.org/addressbook/abview;1"].createInstance(
       Ci.nsIAbView
     );
   }
 
   var actualSortColumn = gAbView.setView(
     directory,
     GetAbViewListener(),
     sortColumn,
     sortDirection
   );
 
   gAbResultsTree.view = gAbView.QueryInterface(Ci.nsITreeView);
+  window.dispatchEvent(new CustomEvent("viewchange"));
 
   UpdateSortIndicators(actualSortColumn, sortDirection);
 
   // If the selected address book is LDAP and the search box is empty,
   // inform the user of the empty results pane.
   let abResultsTree = document.getElementById("abResultsTree");
   let cardViewOuterBox = document.getElementById("CardViewOuterBox");
   let blankResultsPaneMessageBox = document.getElementById(
--- a/mailnews/addrbook/src/nsAbView.cpp
+++ b/mailnews/addrbook/src/nsAbView.cpp
@@ -174,28 +174,26 @@ NS_IMETHODIMP nsAbView::SetView(nsIAbDir
     rv = RemoveCardAt(i);
     NS_ASSERTION(NS_SUCCEEDED(rv), "remove card failed");
   }
 
   // We replace all cards so any sorting is no longer valid.
   mSortColumn.AssignLiteral("");
   mSortDirection.AssignLiteral("");
 
-  nsCString uri = EmptyCString();
-  if (aAddressBook) {
-    aAddressBook->GetURI(uri);
-  }
+  nsCString uri;
+  aAddressBook->GetURI(uri);
   int32_t searchBegin = uri.FindChar('?');
   nsCString searchQuery(Substring(uri, searchBegin));
   // This is a special case, a workaround basically, to just have all ABs.
   if (searchQuery.EqualsLiteral("?")) {
     searchQuery.AssignLiteral("");
   }
 
-  if (!aAddressBook) {
+  if (Substring(uri, 0, searchBegin).EqualsLiteral("moz-abdirectory://")) {
     mIsAllDirectoryRootView = true;
     // We have special request case to search all addressbooks, so we need
     // to iterate over all addressbooks.
     // Since the request is for all addressbooks, the URI must have been
     // passed with an extra '?'. We still check it for sanity and trim it here.
     if (searchQuery.Find("??") == 0) searchQuery = Substring(searchQuery, 1);
 
     nsCOMPtr<nsIAbManager> abManager(