Commit fcbcf1f1 authored by Peter Van der Beken's avatar Peter Van der Beken
Browse files

Fix for bug 464114 (nsAutoCompleteController should participate in cycle collection). r=gavin.

parent 369bf054
Loading
Loading
Loading
Loading
+48 −57
Original line number Diff line number Diff line
@@ -59,10 +59,23 @@

static const char *kAutoCompleteSearchCID = "@mozilla.org/autocomplete/search;1?name=";

NS_IMPL_ISUPPORTS4(nsAutoCompleteController, nsIAutoCompleteController,
                                             nsIAutoCompleteObserver,
                                             nsITimerCallback,
                                             nsITreeView)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsAutoCompleteController)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsAutoCompleteController)
  tmp->SetInput(nsnull);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsAutoCompleteController)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInput)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mSearches)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mResults)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAutoCompleteController)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAutoCompleteController)
NS_INTERFACE_TABLE_HEAD(nsAutoCompleteController)
  NS_INTERFACE_TABLE4(nsAutoCompleteController, nsIAutoCompleteController,
                      nsIAutoCompleteObserver, nsITimerCallback, nsITreeView)
  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsAutoCompleteController)
NS_INTERFACE_MAP_END

nsAutoCompleteController::nsAutoCompleteController() :
  mEnterAfterSearch(0),
@@ -77,8 +90,6 @@ nsAutoCompleteController::nsAutoCompleteController() :
  mSearchesOngoing(0),
  mFirstSearchResult(PR_FALSE)
{
  mSearches = do_CreateInstance("@mozilla.org/supports-array;1");
  mResults = do_CreateInstance("@mozilla.org/supports-array;1");
}

nsAutoCompleteController::~nsAutoCompleteController()
@@ -125,7 +136,7 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
    ClearResults();
    if (mIsOpen)
      ClosePopup();
    mSearches->Clear();
    mSearches.Clear();
  }

  mInput = aInput;
@@ -152,8 +163,8 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
  // Initialize our list of search objects
  PRUint32 searchCount;
  aInput->GetSearchCount(&searchCount);
  mResults->SizeTo(searchCount);
  mSearches->SizeTo(searchCount);
  mResults.SetCapacity(searchCount);
  mSearches.SetCapacity(searchCount);
  mMatchCounts.SetLength(searchCount);

  const char *searchCID = kAutoCompleteSearchCID;
@@ -168,7 +179,7 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
    // Use the created cid to get a pointer to the search service and store it for later
    nsCOMPtr<nsIAutoCompleteSearch> search = do_GetService(cid.get());
    if (search)
      mSearches->AppendElement(search);
      mSearches.AppendObject(search);
  }

  return NS_OK;
@@ -477,9 +488,7 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint32 aKey, PRBool *_retval)
#endif
      if (*_retval) {
        // Open the popup if there has been a previous search, or else kick off a new search
        PRUint32 resultCount;
        mResults->Count(&resultCount);
        if (resultCount) {
        if (mResults.Count() > 0) {
          if (mRowCount) {
            OpenPopup();
          }
@@ -547,8 +556,7 @@ nsAutoCompleteController::HandleDelete(PRBool *_retval)
  RowIndexToSearch(index, &searchIndex, &rowIndex);
  NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE);

  nsCOMPtr<nsIAutoCompleteResult> result;
  mResults->GetElementAt(searchIndex, getter_AddRefs(result));
  nsIAutoCompleteResult *result = mResults[searchIndex];
  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);

  nsAutoString search;
@@ -614,8 +622,7 @@ nsAutoCompleteController::GetCommentAt(PRInt32 aIndex, nsAString & _retval)
  RowIndexToSearch(aIndex, &searchIndex, &rowIndex);
  NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE);

  nsCOMPtr<nsIAutoCompleteResult> result;
  mResults->GetElementAt(searchIndex, getter_AddRefs(result));
  nsIAutoCompleteResult *result = mResults[searchIndex];
  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);

  return result->GetCommentAt(rowIndex, _retval);
@@ -629,8 +636,7 @@ nsAutoCompleteController::GetStyleAt(PRInt32 aIndex, nsAString & _retval)
  RowIndexToSearch(aIndex, &searchIndex, &rowIndex);
  NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE);

  nsCOMPtr<nsIAutoCompleteResult> result;
  mResults->GetElementAt(searchIndex, getter_AddRefs(result));
  nsIAutoCompleteResult *result = mResults[searchIndex];
  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);

  return result->GetStyleAt(rowIndex, _retval);
@@ -644,8 +650,7 @@ nsAutoCompleteController::GetImageAt(PRInt32 aIndex, nsAString & _retval)
  RowIndexToSearch(aIndex, &searchIndex, &rowIndex);
  NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE);

  nsCOMPtr<nsIAutoCompleteResult> result;
  mResults->GetElementAt(searchIndex, getter_AddRefs(result));
  nsIAutoCompleteResult *result = mResults[searchIndex];
  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);

  return result->GetImageAt(rowIndex, _retval);
@@ -673,12 +678,9 @@ NS_IMETHODIMP
nsAutoCompleteController::OnSearchResult(nsIAutoCompleteSearch *aSearch, nsIAutoCompleteResult* aResult)
{
  // look up the index of the search which is returning
  PRUint32 count;
  mSearches->Count(&count);
  PRUint32 count = mSearches.Count();
  for (PRUint32 i = 0; i < count; ++i) {
    nsCOMPtr<nsIAutoCompleteSearch> search;
    mSearches->GetElementAt(i, getter_AddRefs(search));
    if (search == aSearch) {
    if (mSearches[i] == aSearch) {
      ProcessResult(i, aResult);
    }
  }
@@ -978,13 +980,12 @@ nsAutoCompleteController::StartSearch()

  // Cache the current results so that we can pass these through to all the
  // searches without loosing them
  nsresult rv;
  nsCOMPtr<nsISupportsArray> resultCache;
  rv = mResults->Clone(getter_AddRefs(resultCache));
  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMArray<nsIAutoCompleteResult> resultCache;
  if (!resultCache.AppendObjects(mResults)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  PRUint32 count;
  mSearches->Count(&count);
  PRUint32 count = mSearches.Count();
  mSearchesOngoing = count;
  mFirstSearchResult = PR_TRUE;

@@ -993,10 +994,8 @@ nsAutoCompleteController::StartSearch()

  PRUint32 searchesFailed = 0;
  for (PRUint32 i = 0; i < count; ++i) {
    nsCOMPtr<nsIAutoCompleteSearch> search;
    mSearches->GetElementAt(i, getter_AddRefs(search));
    nsCOMPtr<nsIAutoCompleteResult> result;
    resultCache->GetElementAt(i, getter_AddRefs(result));
    nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i];
    nsIAutoCompleteResult *result = resultCache.SafeObjectAt(i);

    if (result) {
      PRUint16 searchResult;
@@ -1007,7 +1006,7 @@ nsAutoCompleteController::StartSearch()
    }

    nsAutoString searchParam;
    rv = input->GetSearchParam(searchParam);
    nsresult rv = input->GetSearchParam(searchParam);
    if (NS_FAILED(rv))
        return rv;

@@ -1032,12 +1031,10 @@ nsAutoCompleteController::StopSearch()

  // Stop any ongoing asynchronous searches
  if (mSearchStatus == nsIAutoCompleteController::STATUS_SEARCHING) {
    PRUint32 count;
    mSearches->Count(&count);
    PRUint32 count = mSearches.Count();

    for (PRUint32 i = 0; i < count; ++i) {
      nsCOMPtr<nsIAutoCompleteSearch> search;
      mSearches->GetElementAt(i, getter_AddRefs(search));
      nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i];
      search->StopSearch();
    }
    mSearchesOngoing = 0;
@@ -1119,11 +1116,9 @@ nsAutoCompleteController::EnterMatch(PRBool aIsPopupSelection)
    if (forceComplete && value.IsEmpty()) {
      // Since nothing was selected, and forceComplete is specified, that means
      // we have to find the first default match and enter it instead
      PRUint32 count;
      mResults->Count(&count);
      PRUint32 count = mResults.Count();
      for (PRUint32 i = 0; i < count; ++i) {
        nsCOMPtr<nsIAutoCompleteResult> result;
        mResults->GetElementAt(i, getter_AddRefs(result));
        nsIAutoCompleteResult *result = mResults[i];

        if (result) {
          PRInt32 defaultIndex;
@@ -1214,15 +1209,15 @@ nsAutoCompleteController::ProcessResult(PRInt32 aSearchIndex, nsIAutoCompleteRes
  if (aResult)
    aResult->GetMatchCount(&matchCount);

  PRInt32 oldIndex = mResults->IndexOf(aResult);
  PRInt32 oldIndex = mResults.IndexOf(aResult);
  if (oldIndex == -1) {
    // cache the result
    mResults->AppendElement(aResult);
    mResults.AppendObject(aResult);
    mMatchCounts.AppendElement(matchCount);
  }
  else {
    // replace the cached result
    mResults->ReplaceElementAt(aResult, oldIndex);
    mResults.ReplaceObjectAt(aResult, oldIndex);
    oldMatchCount = mMatchCounts[aSearchIndex];
    mMatchCounts[oldIndex] = matchCount;
  }
@@ -1313,7 +1308,7 @@ nsAutoCompleteController::ClearResults()
{
  PRInt32 oldRowCount = mRowCount;
  mRowCount = 0;
  mResults->Clear();
  mResults.Clear();
  mMatchCounts.Clear();
  if (oldRowCount != 0) {
    if (mTree)
@@ -1353,8 +1348,7 @@ nsAutoCompleteController::CompleteDefaultIndex(PRInt32 aSearchIndex)
  if (!shouldComplete)
    return NS_OK;

  nsCOMPtr<nsIAutoCompleteResult> result;
  mResults->GetElementAt(aSearchIndex, getter_AddRefs(result));
  nsIAutoCompleteResult *result = mResults[aSearchIndex];
  NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE);

  // The search must explicitly provide a default index in order
@@ -1437,8 +1431,7 @@ nsAutoCompleteController::GetResultValueAt(PRInt32 aIndex, PRBool aValueOnly, ns
  RowIndexToSearch(aIndex, &searchIndex, &rowIndex);
  NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE);

  nsCOMPtr<nsIAutoCompleteResult> result;
  mResults->GetElementAt(searchIndex, getter_AddRefs(result));
  nsIAutoCompleteResult *result = mResults[searchIndex];
  NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE);

  PRUint16 searchResult;
@@ -1467,15 +1460,13 @@ nsAutoCompleteController::RowIndexToSearch(PRInt32 aRowIndex, PRInt32 *aSearchIn
  *aSearchIndex = -1;
  *aItemIndex = -1;

  PRUint32 count;
  mSearches->Count(&count);
  PRUint32 count = mSearches.Count();
  PRUint32 index = 0;

  // Move index through the results of each registered nsIAutoCompleteSearch
  // until we find the given row
  for (PRUint32 i = 0; i < count; ++i) {
    nsCOMPtr<nsIAutoCompleteResult> result;
    mResults->GetElementAt(i, getter_AddRefs(result));
    nsIAutoCompleteResult *result = mResults[i];
    if (!result)
      continue;

+8 −5
Original line number Diff line number Diff line
@@ -48,9 +48,10 @@
#include "nsString.h"
#include "nsITreeView.h"
#include "nsITreeSelection.h"
#include "nsISupportsArray.h"
#include "nsITimer.h"
#include "nsTArray.h"
#include "nsCOMArray.h"
#include "nsCycleCollectionParticipant.h"

class nsAutoCompleteController : public nsIAutoCompleteController,
                                 public nsIAutoCompleteObserver,
@@ -58,7 +59,9 @@ class nsAutoCompleteController : public nsIAutoCompleteController,
                                 public nsITreeView
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAutoCompleteController,
                                           nsIAutoCompleteController)
  NS_DECL_NSIAUTOCOMPLETECONTROLLER
  NS_DECL_NSIAUTOCOMPLETEOBSERVER
  NS_DECL_NSITREEVIEW
@@ -94,8 +97,8 @@ protected:
  
  nsCOMPtr<nsIAutoCompleteInput> mInput;

  nsCOMPtr<nsISupportsArray> mSearches;
  nsCOMPtr<nsISupportsArray> mResults;
  nsCOMArray<nsIAutoCompleteSearch> mSearches;
  nsCOMArray<nsIAutoCompleteResult> mResults;
  nsTArray<PRUint32> mMatchCounts;
  
  nsCOMPtr<nsITimer> mTimer;