dom/bindings/DOMString.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef mozilla_dom_DOMString_h
     7 #define mozilla_dom_DOMString_h
     9 #include "nsStringGlue.h"
    10 #include "nsStringBuffer.h"
    11 #include "mozilla/Assertions.h"
    12 #include "mozilla/Attributes.h"
    13 #include "mozilla/Maybe.h"
    14 #include "nsDOMString.h"
    15 #include "nsIAtom.h"
    17 namespace mozilla {
    18 namespace dom {
    20 /**
    21  * A class for representing string return values.  This can be either passed to
    22  * callees that have an nsString or nsAString out param or passed to a callee
    23  * that actually knows about this class and can work with it.  Such a callee may
    24  * call SetStringBuffer or SetOwnedString or SetOwnedAtom on this object, but
    25  * only if it plans to keep holding a strong ref to the internal stringbuffer!
    26  *
    27  * The proper way to store a value in this class is to either to do nothing
    28  * (which leaves this as an empty string), to call SetStringBuffer with a
    29  * non-null stringbuffer, to call SetOwnedString, to call SetOwnedAtom, to call
    30  * SetNull(), or to call AsAString() and set the value in the resulting
    31  * nsString.  These options are mutually exclusive! Don't do more than one of
    32  * them.
    33  *
    34  * The proper way to extract a value is to check IsNull().  If not null, then
    35  * check HasStringBuffer().  If that's true, check for a zero length, and if the
    36  * length is nonzero call StringBuffer().  If the length is zero this is the
    37  * empty string.  If HasStringBuffer() returns false, call AsAString() and get
    38  * the value from that.
    39  */
    40 class MOZ_STACK_CLASS DOMString {
    41 public:
    42   DOMString()
    43     : mStringBuffer(nullptr)
    44     , mLength(0)
    45     , mIsNull(false)
    46   {}
    47   ~DOMString()
    48   {
    49     MOZ_ASSERT(mString.empty() || !mStringBuffer,
    50                "Shouldn't have both present!");
    51   }
    53   operator nsString&()
    54   {
    55     return AsAString();
    56   }
    58   nsString& AsAString()
    59   {
    60     MOZ_ASSERT(!mStringBuffer, "We already have a stringbuffer?");
    61     MOZ_ASSERT(!mIsNull, "We're already set as null");
    62     if (mString.empty()) {
    63       mString.construct();
    64     }
    65     return mString.ref();
    66   }
    68   bool HasStringBuffer() const
    69   {
    70     MOZ_ASSERT(mString.empty() || !mStringBuffer,
    71                "Shouldn't have both present!");
    72     MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
    73     return mString.empty();
    74   }
    76   // Get the stringbuffer.  This can only be called if HasStringBuffer()
    77   // returned true and StringBufferLength() is nonzero.  If that's true, it will
    78   // never return null.
    79   nsStringBuffer* StringBuffer() const
    80   {
    81     MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
    82     MOZ_ASSERT(HasStringBuffer(),
    83                "Don't ask for the stringbuffer if we don't have it");
    84     MOZ_ASSERT(StringBufferLength() != 0, "Why are you asking for this?");
    85     MOZ_ASSERT(mStringBuffer,
    86                "If our length is nonzero, we better have a stringbuffer.");
    87     return mStringBuffer;
    88   }
    90   // Get the length of the stringbuffer.  Can only be called if
    91   // HasStringBuffer().
    92   uint32_t StringBufferLength() const
    93   {
    94     MOZ_ASSERT(HasStringBuffer(), "Don't call this if there is no stringbuffer");
    95     return mLength;
    96   }
    98   void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength)
    99   {
   100     MOZ_ASSERT(mString.empty(), "We already have a string?");
   101     MOZ_ASSERT(!mIsNull, "We're already set as null");
   102     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
   103     MOZ_ASSERT(aStringBuffer, "Why are we getting null?");
   104     mStringBuffer = aStringBuffer;
   105     mLength = aLength;
   106   }
   108   void SetOwnedString(const nsAString& aString)
   109   {
   110     MOZ_ASSERT(mString.empty(), "We already have a string?");
   111     MOZ_ASSERT(!mIsNull, "We're already set as null");
   112     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
   113     nsStringBuffer* buf = nsStringBuffer::FromString(aString);
   114     if (buf) {
   115       SetStringBuffer(buf, aString.Length());
   116     } else if (aString.IsVoid()) {
   117       SetNull();
   118     } else if (!aString.IsEmpty()) {
   119       AsAString() = aString;
   120     }
   121   }
   123   enum NullHandling
   124   {
   125     eTreatNullAsNull,
   126     eTreatNullAsEmpty,
   127     eNullNotExpected
   128   };
   130   void SetOwnedAtom(nsIAtom* aAtom, NullHandling aNullHandling)
   131   {
   132     MOZ_ASSERT(mString.empty(), "We already have a string?");
   133     MOZ_ASSERT(!mIsNull, "We're already set as null");
   134     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
   135     MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected);
   136     if (aNullHandling == eNullNotExpected || aAtom) {
   137       SetStringBuffer(aAtom->GetStringBuffer(), aAtom->GetLength());
   138     } else if (aNullHandling == eTreatNullAsNull) {
   139       SetNull();
   140     }
   141   }
   143   void SetNull()
   144   {
   145     MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null");
   146     MOZ_ASSERT(mString.empty(), "Should have no string if null");
   147     mIsNull = true;
   148   }
   150   bool IsNull() const
   151   {
   152     MOZ_ASSERT(!mStringBuffer || mString.empty(),
   153                "How could we have a stringbuffer and a nonempty string?");
   154     return mIsNull || (!mString.empty() && mString.ref().IsVoid());
   155   }
   157   void ToString(nsAString& aString)
   158   {
   159     if (IsNull()) {
   160       SetDOMStringToNull(aString);
   161     } else if (HasStringBuffer()) {
   162       if (StringBufferLength() == 0) {
   163         aString.Truncate();
   164       } else {
   165         StringBuffer()->ToString(StringBufferLength(), aString);
   166       }
   167     } else {
   168       aString = AsAString();
   169     }
   170   }
   172 private:
   173   // We need to be able to act like a string as needed
   174   Maybe<nsAutoString> mString;
   176   // For callees that know we exist, we can be a stringbuffer/length/null-flag
   177   // triple.
   178   nsStringBuffer* mStringBuffer;
   179   uint32_t mLength;
   180   bool mIsNull;
   181 };
   183 } // namespace dom
   184 } // namespace mozilla
   186 #endif // mozilla_dom_DOMString_h

mercurial