dom/base/URLSearchParams.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 #include "URLSearchParams.h"
     7 #include "mozilla/dom/URLSearchParamsBinding.h"
     9 namespace mozilla {
    10 namespace dom {
    12 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(URLSearchParams, mObservers)
    13 NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearchParams)
    14 NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams)
    16 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URLSearchParams)
    17   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    18   NS_INTERFACE_MAP_ENTRY(nsISupports)
    19 NS_INTERFACE_MAP_END
    21 URLSearchParams::URLSearchParams()
    22 {
    23   SetIsDOMBinding();
    24 }
    26 URLSearchParams::~URLSearchParams()
    27 {
    28   DeleteAll();
    29 }
    31 JSObject*
    32 URLSearchParams::WrapObject(JSContext* aCx)
    33 {
    34   return URLSearchParamsBinding::Wrap(aCx, this);
    35 }
    37 /* static */ already_AddRefed<URLSearchParams>
    38 URLSearchParams::Constructor(const GlobalObject& aGlobal,
    39                              const nsAString& aInit,
    40                              ErrorResult& aRv)
    41 {
    42   nsRefPtr<URLSearchParams> sp = new URLSearchParams();
    43   sp->ParseInput(NS_ConvertUTF16toUTF8(aInit), nullptr);
    44   return sp.forget();
    45 }
    47 /* static */ already_AddRefed<URLSearchParams>
    48 URLSearchParams::Constructor(const GlobalObject& aGlobal,
    49                              URLSearchParams& aInit,
    50                              ErrorResult& aRv)
    51 {
    52   nsRefPtr<URLSearchParams> sp = new URLSearchParams();
    53   aInit.mSearchParams.EnumerateRead(CopyEnumerator, sp);
    54   return sp.forget();
    55 }
    57 void
    58 URLSearchParams::ParseInput(const nsACString& aInput,
    59                             URLSearchParamsObserver* aObserver)
    60 {
    61   // Remove all the existing data before parsing a new input.
    62   DeleteAll();
    64   nsACString::const_iterator start, end;
    65   aInput.BeginReading(start);
    66   aInput.EndReading(end);
    67   nsACString::const_iterator iter(start);
    69   while (start != end) {
    70     nsAutoCString string;
    72     if (FindCharInReadable('&', iter, end)) {
    73       string.Assign(Substring(start, iter));
    74       start = ++iter;
    75     } else {
    76       string.Assign(Substring(start, end));
    77       start = end;
    78     }
    80     if (string.IsEmpty()) {
    81       continue;
    82     }
    84     nsACString::const_iterator eqStart, eqEnd;
    85     string.BeginReading(eqStart);
    86     string.EndReading(eqEnd);
    87     nsACString::const_iterator eqIter(eqStart);
    89     nsAutoCString name;
    90     nsAutoCString value;
    92     if (FindCharInReadable('=', eqIter, eqEnd)) {
    93       name.Assign(Substring(eqStart, eqIter));
    95       ++eqIter;
    96       value.Assign(Substring(eqIter, eqEnd));
    97     } else {
    98       name.Assign(string);
    99     }
   101     nsAutoCString decodedName;
   102     DecodeString(name, decodedName);
   104     nsAutoCString decodedValue;
   105     DecodeString(value, decodedValue);
   107     AppendInternal(NS_ConvertUTF8toUTF16(decodedName),
   108                    NS_ConvertUTF8toUTF16(decodedValue));
   109   }
   111   NotifyObservers(aObserver);
   112 }
   114 void
   115 URLSearchParams::DecodeString(const nsACString& aInput, nsACString& aOutput)
   116 {
   117   nsACString::const_iterator start, end;
   118   aInput.BeginReading(start);
   119   aInput.EndReading(end);
   121   while (start != end) {
   122     // replace '+' with U+0020
   123     if (*start == '+') {
   124       aOutput.Append(' ');
   125       ++start;
   126       continue;
   127     }
   129     // Percent decode algorithm
   130     if (*start == '%') {
   131       nsACString::const_iterator first(start);
   132       ++first;
   134       nsACString::const_iterator second(first);
   135       ++second;
   137 #define ASCII_HEX_DIGIT( x )    \
   138   ((x >= 0x41 && x <= 0x46) ||  \
   139    (x >= 0x61 && x <= 0x66) ||  \
   140    (x >= 0x30 && x <= 0x39))
   142 #define HEX_DIGIT( x )              \
   143    (*x >= 0x30 && *x <= 0x39        \
   144      ? *x - 0x30                    \
   145      : (*x >= 0x41 && *x <= 0x46    \
   146         ? *x - 0x37                 \
   147         : *x - 0x57))
   149       if (first != end && second != end &&
   150           ASCII_HEX_DIGIT(*first) && ASCII_HEX_DIGIT(*second)) {
   151         aOutput.Append(HEX_DIGIT(first) * 16 + HEX_DIGIT(second));
   152         start = ++second;
   153         continue;
   155       } else {
   156         aOutput.Append('%');
   157         ++start;
   158         continue;
   159       }
   160     }
   162     aOutput.Append(*start);
   163     ++start;
   164   }
   165 }
   167 /* static */ PLDHashOperator
   168 URLSearchParams::CopyEnumerator(const nsAString& aName,
   169                                 nsTArray<nsString>* aArray,
   170                                 void *userData)
   171 {
   172   URLSearchParams* aSearchParams = static_cast<URLSearchParams*>(userData);
   174   nsTArray<nsString>* newArray = new nsTArray<nsString>();
   175   newArray->AppendElements(*aArray);
   177   aSearchParams->mSearchParams.Put(aName, newArray);
   178   return PL_DHASH_NEXT;
   179 }
   181 void
   182 URLSearchParams::AddObserver(URLSearchParamsObserver* aObserver)
   183 {
   184   MOZ_ASSERT(aObserver);
   185   MOZ_ASSERT(!mObservers.Contains(aObserver));
   186   mObservers.AppendElement(aObserver);
   187 }
   189 void
   190 URLSearchParams::RemoveObserver(URLSearchParamsObserver* aObserver)
   191 {
   192   MOZ_ASSERT(aObserver);
   193   mObservers.RemoveElement(aObserver);
   194 }
   196 void
   197 URLSearchParams::Get(const nsAString& aName, nsString& aRetval)
   198 {
   199   nsTArray<nsString>* array;
   200   if (!mSearchParams.Get(aName, &array)) {
   201     aRetval.Truncate();
   202     return;
   203   }
   205   aRetval.Assign(array->ElementAt(0));
   206 }
   208 void
   209 URLSearchParams::GetAll(const nsAString& aName, nsTArray<nsString>& aRetval)
   210 {
   211   nsTArray<nsString>* array;
   212   if (!mSearchParams.Get(aName, &array)) {
   213     return;
   214   }
   216   aRetval.AppendElements(*array);
   217 }
   219 void
   220 URLSearchParams::Set(const nsAString& aName, const nsAString& aValue)
   221 {
   222   nsTArray<nsString>* array;
   223   if (!mSearchParams.Get(aName, &array)) {
   224     array = new nsTArray<nsString>();
   225     array->AppendElement(aValue);
   226     mSearchParams.Put(aName, array);
   227   } else {
   228     array->ElementAt(0) = aValue;
   229   }
   231   NotifyObservers(nullptr);
   232 }
   234 void
   235 URLSearchParams::Append(const nsAString& aName, const nsAString& aValue)
   236 {
   237   AppendInternal(aName, aValue);
   238   NotifyObservers(nullptr);
   239 }
   241 void
   242 URLSearchParams::AppendInternal(const nsAString& aName, const nsAString& aValue)
   243 {
   244   nsTArray<nsString>* array;
   245   if (!mSearchParams.Get(aName, &array)) {
   246     array = new nsTArray<nsString>();
   247     mSearchParams.Put(aName, array);
   248   }
   250   array->AppendElement(aValue);
   251 }
   253 bool
   254 URLSearchParams::Has(const nsAString& aName)
   255 {
   256   return mSearchParams.Get(aName, nullptr);
   257 }
   259 void
   260 URLSearchParams::Delete(const nsAString& aName)
   261 {
   262   nsTArray<nsString>* array;
   263   if (!mSearchParams.Get(aName, &array)) {
   264     return;
   265   }
   267   mSearchParams.Remove(aName);
   269   NotifyObservers(nullptr);
   270 }
   272 void
   273 URLSearchParams::DeleteAll()
   274 {
   275   mSearchParams.Clear();
   276 }
   278 class MOZ_STACK_CLASS SerializeData
   279 {
   280 public:
   281   SerializeData()
   282     : mFirst(true)
   283   {}
   285   nsAutoString mValue;
   286   bool mFirst;
   288   void Serialize(const nsCString& aInput)
   289   {
   290     const unsigned char* p = (const unsigned char*) aInput.get();
   292     while (p && *p) {
   293       // ' ' to '+'
   294       if (*p == 0x20) {
   295         mValue.Append(0x2B);
   296       // Percent Encode algorithm
   297       } else if (*p == 0x2A || *p == 0x2D || *p == 0x2E ||
   298                  (*p >= 0x30 && *p <= 0x39) ||
   299                  (*p >= 0x41 && *p <= 0x5A) || *p == 0x5F ||
   300                  (*p >= 0x61 && *p <= 0x7A)) {
   301         mValue.Append(*p);
   302       } else {
   303         mValue.AppendPrintf("%%%X", *p);
   304       }
   306       ++p;
   307     }
   308   }
   309 };
   311 void
   312 URLSearchParams::Serialize(nsAString& aValue) const
   313 {
   314   SerializeData data;
   315   mSearchParams.EnumerateRead(SerializeEnumerator, &data);
   316   aValue.Assign(data.mValue);
   317 }
   319 /* static */ PLDHashOperator
   320 URLSearchParams::SerializeEnumerator(const nsAString& aName,
   321                                      nsTArray<nsString>* aArray,
   322                                      void *userData)
   323 {
   324   SerializeData* data = static_cast<SerializeData*>(userData);
   326   for (uint32_t i = 0, len = aArray->Length(); i < len; ++i) {
   327     if (data->mFirst) {
   328       data->mFirst = false;
   329     } else {
   330       data->mValue.Append(NS_LITERAL_STRING("&"));
   331     }
   333     data->Serialize(NS_ConvertUTF16toUTF8(aName));
   334     data->mValue.Append(NS_LITERAL_STRING("="));
   335     data->Serialize(NS_ConvertUTF16toUTF8(aArray->ElementAt(i)));
   336   }
   338   return PL_DHASH_NEXT;
   339 }
   341 void
   342 URLSearchParams::NotifyObservers(URLSearchParamsObserver* aExceptObserver)
   343 {
   344   for (uint32_t i = 0; i < mObservers.Length(); ++i) {
   345     if (mObservers[i] != aExceptObserver) {
   346       mObservers[i]->URLSearchParamsUpdated();
   347     }
   348   }
   349 }
   351 } // namespace dom
   352 } // namespace mozilla

mercurial