1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_WindowFeatures_h 8 #define mozilla_dom_WindowFeatures_h 9 10 #include "nsString.h" 11 #include "mozilla/Assertions.h" // MOZ_ASSERT 12 #include "mozilla/HashTable.h" // mozilla::HashMap 13 14 #include "nsStringFwd.h" // nsCString, nsACString, nsAutoCString, nsLiteralCString 15 #include "nsTStringHasher.h" // mozilla::DefaultHasher<nsCString> 16 17 namespace mozilla { 18 namespace dom { 19 20 // Represents `tokenizedFeatures` in 21 // https://html.spec.whatwg.org/multipage/window-object.html#concept-window-open-features-tokenize 22 // with accessor methods for values. 23 class WindowFeatures { 24 public: 25 WindowFeatures() = default; 26 27 WindowFeatures(const WindowFeatures& aOther) = delete; 28 WindowFeatures& operator=(const WindowFeatures& aOther) = delete; 29 30 WindowFeatures(WindowFeatures&& aOther) = delete; 31 WindowFeatures& operator=(WindowFeatures&& aOther) = delete; 32 33 // Tokenizes `aFeatures` and stores the result map in member field. 34 // This should be called at the begining, only once. 35 // 36 // Returns true if successfully tokenized, false otherwise. 37 bool Tokenize(const nsACString& aFeatures); 38 39 // Returns true if the `aName` feature is specified. 40 template <size_t N> Exists(const char (& aName)[N])41 bool Exists(const char (&aName)[N]) const { 42 MOZ_ASSERT(IsLowerCase(aName)); 43 nsLiteralCString name(aName); 44 return tokenizedFeatures_.has(name); 45 } 46 47 // Returns string value of `aName` feature. 48 // The feature must exist. 49 template <size_t N> Get(const char (& aName)[N])50 const nsCString& Get(const char (&aName)[N]) const { 51 MOZ_ASSERT(IsLowerCase(aName)); 52 nsLiteralCString name(aName); 53 auto p = tokenizedFeatures_.lookup(name); 54 MOZ_ASSERT(p.found()); 55 56 return p->value(); 57 } 58 59 // Returns integer value of `aName` feature. 60 // The feature must exist. 61 template <size_t N> GetInt(const char (& aName)[N])62 int32_t GetInt(const char (&aName)[N]) const { 63 const nsCString& value = Get(aName); 64 return ParseIntegerWithFallback(value); 65 } 66 67 // Returns bool value of `aName` feature. 68 // The feature must exist. 69 template <size_t N> GetBool(const char (& aName)[N])70 bool GetBool(const char (&aName)[N]) const { 71 const nsCString& value = Get(aName); 72 return ParseBool(value); 73 } 74 75 // Returns bool value of `aName` feature. 76 // If the feature doesn't exist, returns `aDefault`. 77 // 78 // If `aPresenceFlag` is provided and the feature exists, it's set to `true`. 79 // (note that the value isn't overwritten if the feature doesn't exist) 80 template <size_t N> 81 bool GetBoolWithDefault(const char (&aName)[N], bool aDefault, 82 bool* aPresenceFlag = nullptr) const { 83 MOZ_ASSERT(IsLowerCase(aName)); 84 nsLiteralCString name(aName); 85 auto p = tokenizedFeatures_.lookup(name); 86 if (p.found()) { 87 if (aPresenceFlag) { 88 *aPresenceFlag = true; 89 } 90 return ParseBool(p->value()); 91 } 92 return aDefault; 93 } 94 95 // Remove the feature from the map. 96 template <size_t N> Remove(const char (& aName)[N])97 void Remove(const char (&aName)[N]) { 98 MOZ_ASSERT(IsLowerCase(aName)); 99 nsLiteralCString name(aName); 100 tokenizedFeatures_.remove(name); 101 } 102 103 // Returns true if there was no feature specified, or all features are 104 // removed by `Remove`. 105 // 106 // Note that this can be true even if `aFeatures` parameter of `Tokenize` 107 // is not empty, in case it contains no feature with non-empty name. IsEmpty()108 bool IsEmpty() const { return tokenizedFeatures_.empty(); } 109 110 // Stringify the map into `aOutput`. 111 // The result can be parsed again with `Tokenize`. 112 void Stringify(nsAutoCString& aOutput); 113 114 private: 115 #ifdef DEBUG 116 // Returns true if `text` does not contain any character that gets modified by 117 // `ToLowerCase`. 118 static bool IsLowerCase(const char* text); 119 #endif 120 121 static int32_t ParseIntegerWithFallback(const nsCString& aValue); 122 static bool ParseBool(const nsCString& aValue); 123 124 // A map from feature name to feature value. 125 // If value is not provided, it's empty string. 126 mozilla::HashMap<nsCString, nsCString> tokenizedFeatures_; 127 }; 128 129 } // namespace dom 130 } // namespace mozilla 131 132 #endif // #ifndef mozilla_dom_WindowFeatures_h 133