Bug 433788 - Crash in [@ nsAutoCompleteController::ClosePopup] due to re-entrancy. r=Enn
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 30 Jul 2014 16:55:47 +0200
changeset 196826 cbe49d980c05bbed628650664231f539ec3c8cb7
parent 196825 6e3a195c264ec475ce229fe24534110255d0d9d1
child 196827 7614df67484e7190d444faf712ac7b55f4304708
push id27225
push userryanvm@gmail.com
push dateWed, 30 Jul 2014 21:02:45 +0000
treeherdermozilla-central@e71c55ff7219 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEnn
bugs433788
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 433788 - Crash in [@ nsAutoCompleteController::ClosePopup] due to re-entrancy. r=Enn
toolkit/components/autocomplete/nsAutoCompleteController.cpp
--- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
@@ -255,21 +255,23 @@ nsAutoCompleteController::HandleText()
 
 NS_IMETHODIMP
 nsAutoCompleteController::HandleEnter(bool aIsPopupSelection, bool *_retval)
 {
   *_retval = false;
   if (!mInput)
     return NS_OK;
 
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
+
   // allow the event through unless there is something selected in the popup
-  mInput->GetPopupOpen(_retval);
+  input->GetPopupOpen(_retval);
   if (*_retval) {
     nsCOMPtr<nsIAutoCompletePopup> popup;
-    mInput->GetPopup(getter_AddRefs(popup));
+    input->GetPopup(getter_AddRefs(popup));
 
     if (popup) {
       int32_t selectedIndex;
       popup->GetSelectedIndex(&selectedIndex);
       *_retval = selectedIndex >= 0;
     }
   }
 
@@ -282,18 +284,20 @@ nsAutoCompleteController::HandleEnter(bo
 
 NS_IMETHODIMP
 nsAutoCompleteController::HandleEscape(bool *_retval)
 {
   *_retval = false;
   if (!mInput)
     return NS_OK;
 
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
+
   // allow the event through if the popup is closed
-  mInput->GetPopupOpen(_retval);
+  input->GetPopupOpen(_retval);
 
   // Stop all searches in case they are async.
   StopSearch();
   ClearResults();
   RevertTextValue();
   ClosePopup();
 
   return NS_OK;
@@ -981,26 +985,28 @@ nsAutoCompleteController::OpenPopup()
 
 nsresult
 nsAutoCompleteController::ClosePopup()
 {
   if (!mInput) {
     return NS_OK;
   }
 
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
+
   bool isOpen = false;
-  mInput->GetPopupOpen(&isOpen);
+  input->GetPopupOpen(&isOpen);
   if (!isOpen)
     return NS_OK;
 
   nsCOMPtr<nsIAutoCompletePopup> popup;
-  mInput->GetPopup(getter_AddRefs(popup));
+  input->GetPopup(getter_AddRefs(popup));
   NS_ENSURE_TRUE(popup != nullptr, NS_ERROR_FAILURE);
   popup->SetSelectedIndex(-1);
-  return mInput->SetPopupOpen(false);
+  return input->SetPopupOpen(false);
 }
 
 nsresult
 nsAutoCompleteController::BeforeSearches()
 {
   NS_ENSURE_STATE(mInput);
 
   mSearchStatus = nsIAutoCompleteController::STATUS_SEARCHING;
@@ -1109,19 +1115,21 @@ nsresult
 nsAutoCompleteController::StartSearches()
 {
   // Don't create a new search timer if we're already waiting for one to fire.
   // If we don't check for this, we won't be able to cancel the original timer
   // and may crash when it fires (bug 236659).
   if (mTimer || !mInput)
     return NS_OK;
 
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
+
   // Get the timeout for delayed searches.
   uint32_t timeout;
-  mInput->GetTimeout(&timeout);
+  input->GetTimeout(&timeout);
 
   uint32_t immediateSearchesCount = mImmediateSearchesCount;
   if (timeout == 0) {
     // All the searches should be executed immediately.
     immediateSearchesCount = mSearches.Length();
   }
 
   if (immediateSearchesCount > 0) {
@@ -1437,29 +1445,31 @@ nsAutoCompleteController::ClearResults()
 }
 
 nsresult
 nsAutoCompleteController::CompleteDefaultIndex(int32_t aResultIndex)
 {
   if (mDefaultIndexCompleted || mBackspaced || mSearchString.Length() == 0 || !mInput)
     return NS_OK;
 
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
+
   int32_t selectionStart;
-  mInput->GetSelectionStart(&selectionStart);
+  input->GetSelectionStart(&selectionStart);
   int32_t selectionEnd;
-  mInput->GetSelectionEnd(&selectionEnd);
+  input->GetSelectionEnd(&selectionEnd);
 
   // Don't try to automatically complete to the first result if there's already
   // a selection or the cursor isn't at the end of the input
   if (selectionEnd != selectionStart ||
       selectionEnd != (int32_t)mSearchString.Length())
     return NS_OK;
 
   bool shouldComplete;
-  mInput->GetCompleteDefaultIndex(&shouldComplete);
+  input->GetCompleteDefaultIndex(&shouldComplete);
   if (!shouldComplete)
     return NS_OK;
 
   nsAutoString resultValue;
   if (NS_SUCCEEDED(GetDefaultCompleteValue(aResultIndex, true, resultValue)))
     CompleteValue(resultValue);
 
   mDefaultIndexCompleted = true;
@@ -1549,24 +1559,25 @@ nsAutoCompleteController::GetDefaultComp
 
   return NS_OK;
 }
 
 nsresult
 nsAutoCompleteController::GetFinalDefaultCompleteValue(nsAString &_retval)
 {
   MOZ_ASSERT(mInput, "Must have a valid input");
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
   nsIAutoCompleteResult *result;
   int32_t defaultIndex = -1;
   nsresult rv = GetDefaultCompleteResult(-1, &result, &defaultIndex);
   if (NS_FAILED(rv)) return rv;
 
   result->GetValueAt(defaultIndex, _retval);
   nsAutoString inputValue;
-  mInput->GetTextValue(inputValue);
+  input->GetTextValue(inputValue);
   if (!_retval.Equals(inputValue, nsCaseInsensitiveStringComparator())) {
     return NS_ERROR_FAILURE;
   }
 
   nsAutoString finalCompleteValue;
   rv = result->GetFinalCompleteValueAt(defaultIndex, finalCompleteValue);
   if (NS_SUCCEEDED(rv)) {
     _retval = finalCompleteValue;
@@ -1579,26 +1590,27 @@ nsAutoCompleteController::GetFinalDefaul
 
 nsresult
 nsAutoCompleteController::CompleteValue(nsString &aValue)
 /* mInput contains mSearchString, which we want to autocomplete to aValue.  If
  * selectDifference is true, select the remaining portion of aValue not
  * contained in mSearchString. */
 {
   MOZ_ASSERT(mInput, "Must have a valid input");
+  nsCOMPtr<nsIAutoCompleteInput> input(mInput);
   const int32_t mSearchStringLength = mSearchString.Length();
   int32_t endSelect = aValue.Length();  // By default, select all of aValue.
 
   if (aValue.IsEmpty() ||
       StringBeginsWith(aValue, mSearchString,
                        nsCaseInsensitiveStringComparator())) {
     // aValue is empty (we were asked to clear mInput), or mSearchString
     // matches the beginning of aValue.  In either case we can simply
     // autocomplete to aValue.
-    mInput->SetTextValue(aValue);
+    input->SetTextValue(aValue);
   } else {
     nsresult rv;
     nsCOMPtr<nsIIOService> ios = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     nsAutoCString scheme;
     if (NS_SUCCEEDED(ios->ExtractScheme(NS_ConvertUTF16toUTF8(aValue), scheme))) {
       // Trying to autocomplete a URI from somewhere other than the beginning.
       // Only succeed if the missing portion is "http://"; otherwise do not
@@ -1608,32 +1620,32 @@ nsAutoCompleteController::CompleteValue(
 
       if ((endSelect < findIndex + mSearchStringLength) ||
           !scheme.LowerCaseEqualsLiteral("http") ||
           !Substring(aValue, findIndex, mSearchStringLength).Equals(
             mSearchString, nsCaseInsensitiveStringComparator())) {
         return NS_OK;
       }
 
-      mInput->SetTextValue(mSearchString +
-                           Substring(aValue, mSearchStringLength + findIndex,
-                                     endSelect));
+      input->SetTextValue(mSearchString +
+                          Substring(aValue, mSearchStringLength + findIndex,
+                                    endSelect));
 
       endSelect -= findIndex; // We're skipping this many characters of aValue.
     } else {
       // Autocompleting something other than a URI from the middle.
       // Use the format "searchstring >> full string" to indicate to the user
       // what we are going to replace their search string with.
-      mInput->SetTextValue(mSearchString + NS_LITERAL_STRING(" >> ") + aValue);
+      input->SetTextValue(mSearchString + NS_LITERAL_STRING(" >> ") + aValue);
 
       endSelect = mSearchString.Length() + 4 + aValue.Length();
     }
   }
 
-  mInput->SelectTextRange(mSearchStringLength, endSelect);
+  input->SelectTextRange(mSearchStringLength, endSelect);
 
   return NS_OK;
 }
 
 nsresult
 nsAutoCompleteController::GetResultLabelAt(int32_t aIndex, nsAString & _retval)
 {
   return GetResultValueLabelAt(aIndex, false, false, _retval);