dom/base/URLSearchParams.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial