Sat, 03 Jan 2015 20:18:00 +0100
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: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
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 | #ifndef nsTreeRows_h__ |
michael@0 | 7 | #define nsTreeRows_h__ |
michael@0 | 8 | |
michael@0 | 9 | #include "nsCOMPtr.h" |
michael@0 | 10 | #include "nsTArray.h" |
michael@0 | 11 | #include "pldhash.h" |
michael@0 | 12 | #include "nsIXULTemplateResult.h" |
michael@0 | 13 | #include "nsTemplateMatch.h" |
michael@0 | 14 | #include "nsIRDFResource.h" |
michael@0 | 15 | |
michael@0 | 16 | |
michael@0 | 17 | /** |
michael@0 | 18 | * This class maintains the state of the XUL tree builder's |
michael@0 | 19 | * rows. It maps a row number to the nsTemplateMatch object that |
michael@0 | 20 | * populates the row. |
michael@0 | 21 | */ |
michael@0 | 22 | class nsTreeRows |
michael@0 | 23 | { |
michael@0 | 24 | public: |
michael@0 | 25 | class iterator; |
michael@0 | 26 | friend class iterator; |
michael@0 | 27 | |
michael@0 | 28 | enum Direction { eDirection_Forwards = +1, eDirection_Backwards = -1 }; |
michael@0 | 29 | |
michael@0 | 30 | enum ContainerType { |
michael@0 | 31 | eContainerType_Unknown = 0, |
michael@0 | 32 | eContainerType_Noncontainer = 1, |
michael@0 | 33 | eContainerType_Container = 2 |
michael@0 | 34 | }; |
michael@0 | 35 | |
michael@0 | 36 | enum ContainerState { |
michael@0 | 37 | eContainerState_Unknown = 0, |
michael@0 | 38 | eContainerState_Open = 1, |
michael@0 | 39 | eContainerState_Closed = 2 |
michael@0 | 40 | }; |
michael@0 | 41 | |
michael@0 | 42 | enum ContainerFill { |
michael@0 | 43 | eContainerFill_Unknown = 0, |
michael@0 | 44 | eContainerFill_Empty = 1, |
michael@0 | 45 | eContainerFill_Nonempty = 2 |
michael@0 | 46 | }; |
michael@0 | 47 | |
michael@0 | 48 | class Subtree; |
michael@0 | 49 | |
michael@0 | 50 | /** |
michael@0 | 51 | * A row in the tree. Contains the match that the row |
michael@0 | 52 | * corresponds to, and a pointer to the row's subtree, if there |
michael@0 | 53 | * are any. |
michael@0 | 54 | */ |
michael@0 | 55 | struct Row { |
michael@0 | 56 | nsTemplateMatch* mMatch; |
michael@0 | 57 | ContainerType mContainerType : 4; |
michael@0 | 58 | ContainerState mContainerState : 4; |
michael@0 | 59 | ContainerFill mContainerFill : 4; |
michael@0 | 60 | |
michael@0 | 61 | Subtree* mSubtree; // XXX eventually move to hashtable |
michael@0 | 62 | }; |
michael@0 | 63 | |
michael@0 | 64 | /** |
michael@0 | 65 | * A subtree in the tree. A subtree contains rows, which may |
michael@0 | 66 | * contain other subtrees. |
michael@0 | 67 | */ |
michael@0 | 68 | class Subtree { |
michael@0 | 69 | protected: |
michael@0 | 70 | friend class nsTreeRows; // so that it can access members, for now |
michael@0 | 71 | |
michael@0 | 72 | /** |
michael@0 | 73 | * The parent subtree; null if we're the root |
michael@0 | 74 | */ |
michael@0 | 75 | Subtree* mParent; |
michael@0 | 76 | |
michael@0 | 77 | /** |
michael@0 | 78 | * The number of immediate children in this subtree |
michael@0 | 79 | */ |
michael@0 | 80 | int32_t mCount; |
michael@0 | 81 | |
michael@0 | 82 | /** |
michael@0 | 83 | * The capacity of the subtree |
michael@0 | 84 | */ |
michael@0 | 85 | int32_t mCapacity; |
michael@0 | 86 | |
michael@0 | 87 | /** |
michael@0 | 88 | * The total number of rows in this subtree, recursively |
michael@0 | 89 | * including child subtrees. |
michael@0 | 90 | */ |
michael@0 | 91 | int32_t mSubtreeSize; |
michael@0 | 92 | |
michael@0 | 93 | /** |
michael@0 | 94 | * The array of rows in the subtree |
michael@0 | 95 | */ |
michael@0 | 96 | Row* mRows; |
michael@0 | 97 | |
michael@0 | 98 | public: |
michael@0 | 99 | /** |
michael@0 | 100 | * Creates a subtree with the specified parent. |
michael@0 | 101 | */ |
michael@0 | 102 | Subtree(Subtree* aParent) |
michael@0 | 103 | : mParent(aParent), |
michael@0 | 104 | mCount(0), |
michael@0 | 105 | mCapacity(0), |
michael@0 | 106 | mSubtreeSize(0), |
michael@0 | 107 | mRows(nullptr) {} |
michael@0 | 108 | |
michael@0 | 109 | ~Subtree(); |
michael@0 | 110 | |
michael@0 | 111 | /** |
michael@0 | 112 | * Return the number of immediate child rows in the subtree |
michael@0 | 113 | */ |
michael@0 | 114 | int32_t Count() const { return mCount; } |
michael@0 | 115 | |
michael@0 | 116 | /** |
michael@0 | 117 | * Return the number of rows in this subtree, as well as all |
michael@0 | 118 | * the subtrees it contains. |
michael@0 | 119 | */ |
michael@0 | 120 | int32_t GetSubtreeSize() const { return mSubtreeSize; } |
michael@0 | 121 | |
michael@0 | 122 | /** |
michael@0 | 123 | * Retrieve the immediate child row at the specified index. |
michael@0 | 124 | */ |
michael@0 | 125 | const Row& operator[](int32_t aIndex) const { |
michael@0 | 126 | NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index"); |
michael@0 | 127 | return mRows[aIndex]; } |
michael@0 | 128 | |
michael@0 | 129 | /** |
michael@0 | 130 | * Retrieve the immediate row at the specified index. |
michael@0 | 131 | */ |
michael@0 | 132 | Row& operator[](int32_t aIndex) { |
michael@0 | 133 | NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index"); |
michael@0 | 134 | return mRows[aIndex]; } |
michael@0 | 135 | |
michael@0 | 136 | /** |
michael@0 | 137 | * Remove all rows from the subtree. |
michael@0 | 138 | */ |
michael@0 | 139 | void Clear(); |
michael@0 | 140 | |
michael@0 | 141 | protected: |
michael@0 | 142 | /** |
michael@0 | 143 | * Insert an immediate child row at the specified index. |
michael@0 | 144 | */ |
michael@0 | 145 | iterator InsertRowAt(nsTemplateMatch* aMatch, int32_t aIndex); |
michael@0 | 146 | |
michael@0 | 147 | /** |
michael@0 | 148 | * Remove an immediate child row from the specified index. |
michael@0 | 149 | */ |
michael@0 | 150 | void RemoveRowAt(int32_t aChildIndex); |
michael@0 | 151 | }; |
michael@0 | 152 | |
michael@0 | 153 | friend class Subtree; |
michael@0 | 154 | |
michael@0 | 155 | protected: |
michael@0 | 156 | /** |
michael@0 | 157 | * A link in the path through the view's tree. |
michael@0 | 158 | */ |
michael@0 | 159 | struct Link { |
michael@0 | 160 | Subtree* mParent; |
michael@0 | 161 | int32_t mChildIndex; |
michael@0 | 162 | |
michael@0 | 163 | Link& |
michael@0 | 164 | operator=(const Link& aLink) { |
michael@0 | 165 | mParent = aLink.mParent; |
michael@0 | 166 | mChildIndex = aLink.mChildIndex; |
michael@0 | 167 | return *this; } |
michael@0 | 168 | |
michael@0 | 169 | bool |
michael@0 | 170 | operator==(const Link& aLink) const { |
michael@0 | 171 | return (mParent == aLink.mParent) |
michael@0 | 172 | && (mChildIndex == aLink.mChildIndex); } |
michael@0 | 173 | |
michael@0 | 174 | Subtree* GetParent() { return mParent; } |
michael@0 | 175 | const Subtree* GetParent() const { return mParent; } |
michael@0 | 176 | |
michael@0 | 177 | int32_t GetChildIndex() const { return mChildIndex; } |
michael@0 | 178 | |
michael@0 | 179 | Row& GetRow() { return (*mParent)[mChildIndex]; } |
michael@0 | 180 | const Row& GetRow() const { return (*mParent)[mChildIndex]; } |
michael@0 | 181 | }; |
michael@0 | 182 | |
michael@0 | 183 | public: |
michael@0 | 184 | /** |
michael@0 | 185 | * An iterator that can be used to traverse the tree view. |
michael@0 | 186 | */ |
michael@0 | 187 | class iterator { |
michael@0 | 188 | protected: |
michael@0 | 189 | int32_t mRowIndex; |
michael@0 | 190 | nsAutoTArray<Link, 8> mLink; |
michael@0 | 191 | |
michael@0 | 192 | void Next(); |
michael@0 | 193 | void Prev(); |
michael@0 | 194 | |
michael@0 | 195 | friend class Subtree; // so InsertRowAt can initialize us |
michael@0 | 196 | friend class nsTreeRows; // so nsTreeRows can initialize us |
michael@0 | 197 | |
michael@0 | 198 | /** |
michael@0 | 199 | * Used by operator[]() to initialize an iterator. |
michael@0 | 200 | */ |
michael@0 | 201 | void Append(Subtree* aParent, int32_t aChildIndex); |
michael@0 | 202 | |
michael@0 | 203 | /** |
michael@0 | 204 | * Used by InsertRowAt() to initialize an iterator. |
michael@0 | 205 | */ |
michael@0 | 206 | void Push(Subtree *aParent, int32_t aChildIndex); |
michael@0 | 207 | |
michael@0 | 208 | /** |
michael@0 | 209 | * Used by operator[]() and InsertRowAt() to initialize an iterator. |
michael@0 | 210 | */ |
michael@0 | 211 | void SetRowIndex(int32_t aRowIndex) { mRowIndex = aRowIndex; } |
michael@0 | 212 | |
michael@0 | 213 | /** |
michael@0 | 214 | * Handy accessors to the top element. |
michael@0 | 215 | */ |
michael@0 | 216 | Link& GetTop() { return mLink[mLink.Length() - 1]; } |
michael@0 | 217 | const Link& GetTop() const { return mLink[mLink.Length() - 1]; } |
michael@0 | 218 | |
michael@0 | 219 | public: |
michael@0 | 220 | iterator() : mRowIndex(-1) {} |
michael@0 | 221 | |
michael@0 | 222 | iterator(const iterator& aIterator); |
michael@0 | 223 | iterator& operator=(const iterator& aIterator); |
michael@0 | 224 | |
michael@0 | 225 | bool operator==(const iterator& aIterator) const; |
michael@0 | 226 | |
michael@0 | 227 | bool operator!=(const iterator& aIterator) const { |
michael@0 | 228 | return !aIterator.operator==(*this); } |
michael@0 | 229 | |
michael@0 | 230 | const Row& operator*() const { return GetTop().GetRow(); } |
michael@0 | 231 | Row& operator*() { return GetTop().GetRow(); } |
michael@0 | 232 | |
michael@0 | 233 | const Row* operator->() const { return &(GetTop().GetRow()); } |
michael@0 | 234 | Row* operator->() { return &(GetTop().GetRow()); } |
michael@0 | 235 | |
michael@0 | 236 | iterator& operator++() { Next(); return *this; } |
michael@0 | 237 | iterator operator++(int) { iterator temp(*this); Next(); return temp; } |
michael@0 | 238 | iterator& operator--() { Prev(); return *this; } |
michael@0 | 239 | iterator operator--(int) { iterator temp(*this); Prev(); return temp; } |
michael@0 | 240 | |
michael@0 | 241 | /** |
michael@0 | 242 | * Return the current parent link |
michael@0 | 243 | */ |
michael@0 | 244 | Subtree* GetParent() { return GetTop().GetParent(); } |
michael@0 | 245 | |
michael@0 | 246 | const Subtree* GetParent() const { return GetTop().GetParent(); } |
michael@0 | 247 | |
michael@0 | 248 | /** |
michael@0 | 249 | * Return the current child index |
michael@0 | 250 | */ |
michael@0 | 251 | int32_t GetChildIndex() const { return GetTop().GetChildIndex(); } |
michael@0 | 252 | |
michael@0 | 253 | /** |
michael@0 | 254 | * Return the depth of the path the iterator is maintaining |
michael@0 | 255 | * into the tree. |
michael@0 | 256 | */ |
michael@0 | 257 | int32_t GetDepth() const { return mLink.Length(); } |
michael@0 | 258 | |
michael@0 | 259 | /** |
michael@0 | 260 | * Return the current row index of the iterator |
michael@0 | 261 | */ |
michael@0 | 262 | int32_t GetRowIndex() const { return mRowIndex; } |
michael@0 | 263 | |
michael@0 | 264 | /** |
michael@0 | 265 | * Pop the iterator up a level. |
michael@0 | 266 | */ |
michael@0 | 267 | iterator& Pop() { mLink.SetLength(GetDepth() - 1); return *this; } |
michael@0 | 268 | }; |
michael@0 | 269 | |
michael@0 | 270 | /** |
michael@0 | 271 | * Retrieve the first element in the view |
michael@0 | 272 | */ |
michael@0 | 273 | iterator First(); |
michael@0 | 274 | |
michael@0 | 275 | /** |
michael@0 | 276 | * Retrieve (one past) the last element in the view |
michael@0 | 277 | */ |
michael@0 | 278 | iterator Last(); |
michael@0 | 279 | |
michael@0 | 280 | /** |
michael@0 | 281 | * Find the row that contains the given resource |
michael@0 | 282 | */ |
michael@0 | 283 | iterator FindByResource(nsIRDFResource* aResource); |
michael@0 | 284 | |
michael@0 | 285 | /** |
michael@0 | 286 | * Find the row that contains the result |
michael@0 | 287 | */ |
michael@0 | 288 | iterator Find(nsIXULTemplateResult* aResult); |
michael@0 | 289 | |
michael@0 | 290 | /** |
michael@0 | 291 | * Retrieve the ith element in the view |
michael@0 | 292 | */ |
michael@0 | 293 | iterator operator[](int32_t aIndex); |
michael@0 | 294 | |
michael@0 | 295 | nsTreeRows() : mRoot(nullptr) {} |
michael@0 | 296 | ~nsTreeRows() {} |
michael@0 | 297 | |
michael@0 | 298 | /** |
michael@0 | 299 | * Ensure that a child subtree exists within the specified parent |
michael@0 | 300 | * at the specified child index within the parent. (In other |
michael@0 | 301 | * words, create a subtree if one doesn't already exist.) |
michael@0 | 302 | */ |
michael@0 | 303 | Subtree* |
michael@0 | 304 | EnsureSubtreeFor(Subtree* aParent, int32_t aChildIndex); |
michael@0 | 305 | |
michael@0 | 306 | /** |
michael@0 | 307 | * Ensure that a child subtree exists at the iterator's position. |
michael@0 | 308 | */ |
michael@0 | 309 | Subtree* |
michael@0 | 310 | EnsureSubtreeFor(iterator& aIterator) { |
michael@0 | 311 | return EnsureSubtreeFor(aIterator.GetParent(), |
michael@0 | 312 | aIterator.GetChildIndex()); } |
michael@0 | 313 | |
michael@0 | 314 | /** |
michael@0 | 315 | * Get the child subtree for the specified parent at the specified |
michael@0 | 316 | * child index. Optionally return the child subtree's size. Will |
michael@0 | 317 | * return `null' if no subtree exists. |
michael@0 | 318 | */ |
michael@0 | 319 | Subtree* |
michael@0 | 320 | GetSubtreeFor(const Subtree* aParent, |
michael@0 | 321 | int32_t aChildIndex, |
michael@0 | 322 | int32_t* aSubtreeSize = nullptr); |
michael@0 | 323 | |
michael@0 | 324 | /** |
michael@0 | 325 | * Retrieve the size of the subtree within the specified parent. |
michael@0 | 326 | */ |
michael@0 | 327 | int32_t |
michael@0 | 328 | GetSubtreeSizeFor(const Subtree* aParent, |
michael@0 | 329 | int32_t aChildIndex) { |
michael@0 | 330 | int32_t size; |
michael@0 | 331 | GetSubtreeFor(aParent, aChildIndex, &size); |
michael@0 | 332 | return size; } |
michael@0 | 333 | |
michael@0 | 334 | /** |
michael@0 | 335 | * Retrieve the size of the subtree within the specified parent. |
michael@0 | 336 | */ |
michael@0 | 337 | int32_t |
michael@0 | 338 | GetSubtreeSizeFor(const iterator& aIterator) { |
michael@0 | 339 | int32_t size; |
michael@0 | 340 | GetSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex(), &size); |
michael@0 | 341 | return size; } |
michael@0 | 342 | |
michael@0 | 343 | /** |
michael@0 | 344 | * Remove the specified subtree for a row, leaving the row itself |
michael@0 | 345 | * intact. |
michael@0 | 346 | */ |
michael@0 | 347 | void |
michael@0 | 348 | RemoveSubtreeFor(Subtree* aParent, int32_t aChildIndex); |
michael@0 | 349 | |
michael@0 | 350 | /** |
michael@0 | 351 | * Remove the specified subtree for a row, leaving the row itself |
michael@0 | 352 | * intact. |
michael@0 | 353 | */ |
michael@0 | 354 | void |
michael@0 | 355 | RemoveSubtreeFor(iterator& aIterator) { |
michael@0 | 356 | RemoveSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex()); } |
michael@0 | 357 | |
michael@0 | 358 | /** |
michael@0 | 359 | * Remove the specified row from the view |
michael@0 | 360 | */ |
michael@0 | 361 | int32_t |
michael@0 | 362 | RemoveRowAt(iterator& aIterator) { |
michael@0 | 363 | iterator temp = aIterator--; |
michael@0 | 364 | Subtree* parent = temp.GetParent(); |
michael@0 | 365 | parent->RemoveRowAt(temp.GetChildIndex()); |
michael@0 | 366 | InvalidateCachedRow(); |
michael@0 | 367 | return parent->Count(); } |
michael@0 | 368 | |
michael@0 | 369 | /** |
michael@0 | 370 | * Insert a new match into the view |
michael@0 | 371 | */ |
michael@0 | 372 | iterator |
michael@0 | 373 | InsertRowAt(nsTemplateMatch* aMatch, Subtree* aSubtree, int32_t aChildIndex) { |
michael@0 | 374 | InvalidateCachedRow(); |
michael@0 | 375 | return aSubtree->InsertRowAt(aMatch, aChildIndex); } |
michael@0 | 376 | |
michael@0 | 377 | /** |
michael@0 | 378 | * Raw access to the rows; e.g., for sorting. |
michael@0 | 379 | */ |
michael@0 | 380 | Row* |
michael@0 | 381 | GetRowsFor(Subtree* aSubtree) { return aSubtree->mRows; } |
michael@0 | 382 | |
michael@0 | 383 | /** |
michael@0 | 384 | * Remove all of the rows |
michael@0 | 385 | */ |
michael@0 | 386 | void Clear(); |
michael@0 | 387 | |
michael@0 | 388 | /** |
michael@0 | 389 | * Return the total number of rows in the tree view. |
michael@0 | 390 | */ |
michael@0 | 391 | int32_t Count() const { return mRoot.GetSubtreeSize(); } |
michael@0 | 392 | |
michael@0 | 393 | /** |
michael@0 | 394 | * Retrieve the root subtree |
michael@0 | 395 | */ |
michael@0 | 396 | Subtree* GetRoot() { return &mRoot; } |
michael@0 | 397 | |
michael@0 | 398 | /** |
michael@0 | 399 | * Set the root resource for the view |
michael@0 | 400 | */ |
michael@0 | 401 | void SetRootResource(nsIRDFResource* aResource) { |
michael@0 | 402 | mRootResource = aResource; } |
michael@0 | 403 | |
michael@0 | 404 | /** |
michael@0 | 405 | * Retrieve the root resource for the view |
michael@0 | 406 | */ |
michael@0 | 407 | nsIRDFResource* GetRootResource() { |
michael@0 | 408 | return mRootResource.get(); } |
michael@0 | 409 | |
michael@0 | 410 | /** |
michael@0 | 411 | * Invalidate the cached row; e.g., because the view has changed |
michael@0 | 412 | * in a way that would corrupt the iterator. |
michael@0 | 413 | */ |
michael@0 | 414 | void |
michael@0 | 415 | InvalidateCachedRow() { mLastRow = iterator(); } |
michael@0 | 416 | |
michael@0 | 417 | protected: |
michael@0 | 418 | /** |
michael@0 | 419 | * The root subtree. |
michael@0 | 420 | */ |
michael@0 | 421 | Subtree mRoot; |
michael@0 | 422 | |
michael@0 | 423 | /** |
michael@0 | 424 | * The root resource for the view |
michael@0 | 425 | */ |
michael@0 | 426 | nsCOMPtr<nsIRDFResource> mRootResource; |
michael@0 | 427 | |
michael@0 | 428 | /** |
michael@0 | 429 | * The last row that was asked for by operator[]. By remembering |
michael@0 | 430 | * this, we can usually avoid the O(n) search through the row |
michael@0 | 431 | * array to find the row at the specified index. |
michael@0 | 432 | */ |
michael@0 | 433 | iterator mLastRow; |
michael@0 | 434 | }; |
michael@0 | 435 | |
michael@0 | 436 | |
michael@0 | 437 | #endif // nsTreeRows_h__ |