Don't generate state keys at all, if there's nothing to get. Bug 388387, r+sr=sicking.
authorbzbarsky@mit.edu
Fri, 20 Jul 2007 20:00:02 -0700
changeset 3727 638e3d4c61ab20bfa40506d1856cf5c0e82af579
parent 3726 d9ba446637ab2d5702105bf8a82db6315f5cb8f7
child 3728 af28791d0ff3bf27076cb16963015a6ca3e2385a
push idunknown
push userunknown
push dateunknown
bugs388387
milestone1.9a7pre
Don't generate state keys at all, if there's nothing to get. Bug 388387, r+sr=sicking.
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
layout/base/nsILayoutHistoryState.h
layout/base/nsLayoutHistoryState.cpp
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1728,17 +1728,17 @@ nsGenericHTMLElement::GetPrimaryPresStat
 {
   NS_ENSURE_ARG_POINTER(aPresState);
   *aPresState = nsnull;
 
   nsresult result = NS_OK;
 
   nsCOMPtr<nsILayoutHistoryState> history;
   nsCAutoString key;
-  GetLayoutHistoryAndKey(aContent, getter_AddRefs(history), key);
+  GetLayoutHistoryAndKey(aContent, PR_FALSE, getter_AddRefs(history), key);
 
   if (history) {
     // Get the pres state for this key, if it doesn't exist, create one
     result = history->GetState(key, aPresState);
     if (!*aPresState) {
       result = NS_NewPresState(aPresState);
       if (NS_SUCCEEDED(result)) {
         result = history->AddState(key, *aPresState);
@@ -1747,16 +1747,17 @@ nsGenericHTMLElement::GetPrimaryPresStat
   }
 
   return result;
 }
 
 
 nsresult
 nsGenericHTMLElement::GetLayoutHistoryAndKey(nsGenericHTMLElement* aContent,
+                                             PRBool aRead,
                                              nsILayoutHistoryState** aHistory,
                                              nsACString& aKey)
 {
   //
   // Get the pres shell
   //
   nsCOMPtr<nsIDocument> doc = aContent->GetDocument();
   if (!doc) {
@@ -1766,16 +1767,21 @@ nsGenericHTMLElement::GetLayoutHistoryAn
   //
   // Get the history (don't bother with the key if the history is not there)
   //
   *aHistory = doc->GetLayoutHistoryState().get();
   if (!*aHistory) {
     return NS_OK;
   }
 
+  if (aRead && !(*aHistory)->HasStates()) {
+    NS_RELEASE(*aHistory);
+    return NS_OK;
+  }
+
   //
   // Get the state key
   //
   nsresult rv = nsContentUtils::GenerateStateKey(aContent, doc,
                                                  nsIStatefulFrame::eNoID,
                                                  aKey);
   if (NS_FAILED(rv)) {
     NS_RELEASE(*aHistory);
@@ -1796,17 +1802,18 @@ nsGenericHTMLElement::GetLayoutHistoryAn
 }
 
 PRBool
 nsGenericHTMLElement::RestoreFormControlState(nsGenericHTMLElement* aContent,
                                               nsIFormControl* aControl)
 {
   nsCOMPtr<nsILayoutHistoryState> history;
   nsCAutoString key;
-  nsresult rv = GetLayoutHistoryAndKey(aContent, getter_AddRefs(history), key);
+  nsresult rv = GetLayoutHistoryAndKey(aContent, PR_TRUE,
+                                       getter_AddRefs(history), key);
   if (!history) {
     return PR_FALSE;
   }
 
   nsPresState *state;
   // Get the pres state for this key
   rv = history->GetState(key, &state);
   if (state) {
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -522,20 +522,23 @@ public:
    */
   static nsresult GetPrimaryPresState(nsGenericHTMLElement* aContent,
                                       nsPresState** aPresState);
   /**
    * Get the layout history object *and* generate the key for a particular
    * piece of content.
    *
    * @param aContent the content to generate the key for
+   * @param aRead if true, won't return a layout history state (and won't
+   *              generate a key) if the layout history state is empty.
    * @param aState the history state object (out param)
    * @param aKey the key (out param)
    */
   static nsresult GetLayoutHistoryAndKey(nsGenericHTMLElement* aContent,
+                                         PRBool aRead,
                                          nsILayoutHistoryState** aState,
                                          nsACString& aKey);
   /**
    * Restore the state for a form control.  Ends up calling
    * nsIFormControl::RestoreState().
    *
    * @param aContent an nsGenericHTMLElement* pointing to the form control
    * @param aControl an nsIFormControl* pointing to the form control
--- a/layout/base/nsILayoutHistoryState.h
+++ b/layout/base/nsILayoutHistoryState.h
@@ -45,18 +45,18 @@
 #define _nsILayoutHistoryState_h
 
 #include "nsISupports.h"
 #include "nsStringFwd.h"
 
 class nsPresState;
 
 #define NS_ILAYOUTHISTORYSTATE_IID \
-{0xe6abfb7c, 0x6624, 0x4b4d, \
-{0x9d, 0xfe, 0xea, 0x62, 0xae, 0xfe, 0x03, 0x31}}
+{ 0x99003f0f, 0x7ade, 0x44a1, \
+ { 0x81, 0x74, 0xe3, 0x6a, 0xa5, 0xbb, 0x6b, 0x10 } }
 
 class nsILayoutHistoryState : public nsISupports {
  public: 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILAYOUTHISTORYSTATE_IID)
 
   /**
    * Set |aState| as the state object for |aKey|.
    * This _transfers_ownership_ of |aState| to the LayoutHistoryState.
@@ -69,16 +69,21 @@ class nsILayoutHistoryState : public nsI
    * Look up the state object for |aKey|.
    */
   NS_IMETHOD GetState(const nsCString& aKey, nsPresState** aState) = 0;
 
   /**
    * Remove the state object for |aKey|.
    */
   NS_IMETHOD RemoveState(const nsCString& aKey) = 0;
+
+  /**
+   * Check whether this history has any states in it
+   */
+  NS_IMETHOD_(PRBool) HasStates() const = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsILayoutHistoryState,
                               NS_ILAYOUTHISTORYSTATE_IID)
 
 nsresult
 NS_NewLayoutHistoryState(nsILayoutHistoryState** aState);
 
--- a/layout/base/nsLayoutHistoryState.cpp
+++ b/layout/base/nsLayoutHistoryState.cpp
@@ -53,16 +53,17 @@ public:
   NS_HIDDEN_(nsresult) Init();
 
   NS_DECL_ISUPPORTS
 
   // nsILayoutHistoryState
   NS_IMETHOD AddState(const nsCString& aKey, nsPresState* aState);
   NS_IMETHOD GetState(const nsCString& aKey, nsPresState** aState);
   NS_IMETHOD RemoveState(const nsCString& aKey);
+  NS_IMETHOD_(PRBool) HasStates() const;
 
 
 private:
   ~nsLayoutHistoryState() {}
 
   nsClassHashtable<nsCStringHashKey,nsPresState> mStates;
 };
 
@@ -111,8 +112,14 @@ nsLayoutHistoryState::GetState(const nsC
 }
 
 NS_IMETHODIMP
 nsLayoutHistoryState::RemoveState(const nsCString& aKey)
 {
   mStates.Remove(aKey);
   return NS_OK;
 }
+
+NS_IMETHODIMP_(PRBool)
+nsLayoutHistoryState::HasStates() const
+{
+  return mStates.Count() != 0;
+}