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: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ |
michael@0 | 2 | /* vim: set ts=2 sw=2 et tw=79: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 5 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | /** |
michael@0 | 8 | * A header for declaring various things that binding implementation headers |
michael@0 | 9 | * might need. The idea is to make binding implementation headers safe to |
michael@0 | 10 | * include anywhere without running into include hell like we do with |
michael@0 | 11 | * BindingUtils.h |
michael@0 | 12 | */ |
michael@0 | 13 | #ifndef mozilla_dom_BindingDeclarations_h__ |
michael@0 | 14 | #define mozilla_dom_BindingDeclarations_h__ |
michael@0 | 15 | |
michael@0 | 16 | #include "nsStringGlue.h" |
michael@0 | 17 | #include "js/Value.h" |
michael@0 | 18 | #include "js/RootingAPI.h" |
michael@0 | 19 | #include "mozilla/Maybe.h" |
michael@0 | 20 | #include "nsCOMPtr.h" |
michael@0 | 21 | #include "nsTArray.h" |
michael@0 | 22 | #include "nsAutoPtr.h" // for nsRefPtr member variables |
michael@0 | 23 | #include "mozilla/dom/DOMString.h" |
michael@0 | 24 | #include "mozilla/dom/OwningNonNull.h" |
michael@0 | 25 | |
michael@0 | 26 | class nsWrapperCache; |
michael@0 | 27 | |
michael@0 | 28 | namespace mozilla { |
michael@0 | 29 | namespace dom { |
michael@0 | 30 | |
michael@0 | 31 | // Struct that serves as a base class for all dictionaries. Particularly useful |
michael@0 | 32 | // so we can use IsBaseOf to detect dictionary template arguments. |
michael@0 | 33 | struct DictionaryBase |
michael@0 | 34 | { |
michael@0 | 35 | protected: |
michael@0 | 36 | bool ParseJSON(JSContext* aCx, const nsAString& aJSON, |
michael@0 | 37 | JS::MutableHandle<JS::Value> aVal); |
michael@0 | 38 | }; |
michael@0 | 39 | |
michael@0 | 40 | // Struct that serves as a base class for all typed arrays and array buffers and |
michael@0 | 41 | // array buffer views. Particularly useful so we can use IsBaseOf to detect |
michael@0 | 42 | // typed array/buffer/view template arguments. |
michael@0 | 43 | struct AllTypedArraysBase { |
michael@0 | 44 | }; |
michael@0 | 45 | |
michael@0 | 46 | // Struct that serves as a base class for all owning unions. |
michael@0 | 47 | // Particularly useful so we can use IsBaseOf to detect owning union |
michael@0 | 48 | // template arguments. |
michael@0 | 49 | struct AllOwningUnionBase { |
michael@0 | 50 | }; |
michael@0 | 51 | |
michael@0 | 52 | |
michael@0 | 53 | struct EnumEntry { |
michael@0 | 54 | const char* value; |
michael@0 | 55 | size_t length; |
michael@0 | 56 | }; |
michael@0 | 57 | |
michael@0 | 58 | class MOZ_STACK_CLASS GlobalObject |
michael@0 | 59 | { |
michael@0 | 60 | public: |
michael@0 | 61 | GlobalObject(JSContext* aCx, JSObject* aObject); |
michael@0 | 62 | |
michael@0 | 63 | JSObject* Get() const |
michael@0 | 64 | { |
michael@0 | 65 | return mGlobalJSObject; |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | nsISupports* GetAsSupports() const; |
michael@0 | 69 | |
michael@0 | 70 | // The context that this returns is not guaranteed to be in the compartment of |
michael@0 | 71 | // the object returned from Get(), in fact it's generally in the caller's |
michael@0 | 72 | // compartment. |
michael@0 | 73 | JSContext* GetContext() const |
michael@0 | 74 | { |
michael@0 | 75 | return mCx; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | bool Failed() const |
michael@0 | 79 | { |
michael@0 | 80 | return !Get(); |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | protected: |
michael@0 | 84 | JS::Rooted<JSObject*> mGlobalJSObject; |
michael@0 | 85 | JSContext* mCx; |
michael@0 | 86 | mutable nsISupports* mGlobalObject; |
michael@0 | 87 | mutable nsCOMPtr<nsISupports> mGlobalObjectRef; |
michael@0 | 88 | }; |
michael@0 | 89 | |
michael@0 | 90 | // Class for representing optional arguments. |
michael@0 | 91 | template<typename T, typename InternalType> |
michael@0 | 92 | class Optional_base |
michael@0 | 93 | { |
michael@0 | 94 | public: |
michael@0 | 95 | Optional_base() |
michael@0 | 96 | {} |
michael@0 | 97 | |
michael@0 | 98 | explicit Optional_base(const T& aValue) |
michael@0 | 99 | { |
michael@0 | 100 | mImpl.construct(aValue); |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | template<typename T1, typename T2> |
michael@0 | 104 | explicit Optional_base(const T1& aValue1, const T2& aValue2) |
michael@0 | 105 | { |
michael@0 | 106 | mImpl.construct(aValue1, aValue2); |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | bool WasPassed() const |
michael@0 | 110 | { |
michael@0 | 111 | return !mImpl.empty(); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | // Return InternalType here so we can work with it usefully. |
michael@0 | 115 | InternalType& Construct() |
michael@0 | 116 | { |
michael@0 | 117 | mImpl.construct(); |
michael@0 | 118 | return mImpl.ref(); |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | template <class T1> |
michael@0 | 122 | InternalType& Construct(const T1 &t1) |
michael@0 | 123 | { |
michael@0 | 124 | mImpl.construct(t1); |
michael@0 | 125 | return mImpl.ref(); |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | template <class T1, class T2> |
michael@0 | 129 | InternalType& Construct(const T1 &t1, const T2 &t2) |
michael@0 | 130 | { |
michael@0 | 131 | mImpl.construct(t1, t2); |
michael@0 | 132 | return mImpl.ref(); |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | void Reset() |
michael@0 | 136 | { |
michael@0 | 137 | if (WasPassed()) { |
michael@0 | 138 | mImpl.destroy(); |
michael@0 | 139 | } |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | const T& Value() const |
michael@0 | 143 | { |
michael@0 | 144 | return mImpl.ref(); |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | // Return InternalType here so we can work with it usefully. |
michael@0 | 148 | InternalType& Value() |
michael@0 | 149 | { |
michael@0 | 150 | return mImpl.ref(); |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | // And an explicit way to get the InternalType even if we're const. |
michael@0 | 154 | const InternalType& InternalValue() const |
michael@0 | 155 | { |
michael@0 | 156 | return mImpl.ref(); |
michael@0 | 157 | } |
michael@0 | 158 | |
michael@0 | 159 | // If we ever decide to add conversion operators for optional arrays |
michael@0 | 160 | // like the ones Nullable has, we'll need to ensure that Maybe<> has |
michael@0 | 161 | // the boolean before the actual data. |
michael@0 | 162 | |
michael@0 | 163 | private: |
michael@0 | 164 | // Forbid copy-construction and assignment |
michael@0 | 165 | Optional_base(const Optional_base& other) MOZ_DELETE; |
michael@0 | 166 | const Optional_base &operator=(const Optional_base &other) MOZ_DELETE; |
michael@0 | 167 | |
michael@0 | 168 | protected: |
michael@0 | 169 | Maybe<InternalType> mImpl; |
michael@0 | 170 | }; |
michael@0 | 171 | |
michael@0 | 172 | template<typename T> |
michael@0 | 173 | class Optional : public Optional_base<T, T> |
michael@0 | 174 | { |
michael@0 | 175 | public: |
michael@0 | 176 | Optional() : |
michael@0 | 177 | Optional_base<T, T>() |
michael@0 | 178 | {} |
michael@0 | 179 | |
michael@0 | 180 | explicit Optional(const T& aValue) : |
michael@0 | 181 | Optional_base<T, T>(aValue) |
michael@0 | 182 | {} |
michael@0 | 183 | }; |
michael@0 | 184 | |
michael@0 | 185 | template<typename T> |
michael@0 | 186 | class Optional<JS::Handle<T> > : |
michael@0 | 187 | public Optional_base<JS::Handle<T>, JS::Rooted<T> > |
michael@0 | 188 | { |
michael@0 | 189 | public: |
michael@0 | 190 | Optional() : |
michael@0 | 191 | Optional_base<JS::Handle<T>, JS::Rooted<T> >() |
michael@0 | 192 | {} |
michael@0 | 193 | |
michael@0 | 194 | Optional(JSContext* cx) : |
michael@0 | 195 | Optional_base<JS::Handle<T>, JS::Rooted<T> >() |
michael@0 | 196 | { |
michael@0 | 197 | this->Construct(cx); |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | Optional(JSContext* cx, const T& aValue) : |
michael@0 | 201 | Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue) |
michael@0 | 202 | {} |
michael@0 | 203 | |
michael@0 | 204 | // Override the const Value() to return the right thing so we're not |
michael@0 | 205 | // returning references to temporaries. |
michael@0 | 206 | JS::Handle<T> Value() const |
michael@0 | 207 | { |
michael@0 | 208 | return this->mImpl.ref(); |
michael@0 | 209 | } |
michael@0 | 210 | |
michael@0 | 211 | // And we have to override the non-const one too, since we're |
michael@0 | 212 | // shadowing the one on the superclass. |
michael@0 | 213 | JS::Rooted<T>& Value() |
michael@0 | 214 | { |
michael@0 | 215 | return this->mImpl.ref(); |
michael@0 | 216 | } |
michael@0 | 217 | }; |
michael@0 | 218 | |
michael@0 | 219 | // A specialization of Optional for JSObject* to make sure that when someone |
michael@0 | 220 | // calls Construct() on it we will pre-initialized the JSObject* to nullptr so |
michael@0 | 221 | // it can be traced safely. |
michael@0 | 222 | template<> |
michael@0 | 223 | class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*> |
michael@0 | 224 | { |
michael@0 | 225 | public: |
michael@0 | 226 | Optional() : |
michael@0 | 227 | Optional_base<JSObject*, JSObject*>() |
michael@0 | 228 | {} |
michael@0 | 229 | |
michael@0 | 230 | explicit Optional(JSObject* aValue) : |
michael@0 | 231 | Optional_base<JSObject*, JSObject*>(aValue) |
michael@0 | 232 | {} |
michael@0 | 233 | |
michael@0 | 234 | // Don't allow us to have an uninitialized JSObject* |
michael@0 | 235 | JSObject*& Construct() |
michael@0 | 236 | { |
michael@0 | 237 | // The Android compiler sucks and thinks we're trying to construct |
michael@0 | 238 | // a JSObject* from an int if we don't cast here. :( |
michael@0 | 239 | return Optional_base<JSObject*, JSObject*>::Construct( |
michael@0 | 240 | static_cast<JSObject*>(nullptr)); |
michael@0 | 241 | } |
michael@0 | 242 | |
michael@0 | 243 | template <class T1> |
michael@0 | 244 | JSObject*& Construct(const T1& t1) |
michael@0 | 245 | { |
michael@0 | 246 | return Optional_base<JSObject*, JSObject*>::Construct(t1); |
michael@0 | 247 | } |
michael@0 | 248 | }; |
michael@0 | 249 | |
michael@0 | 250 | // A specialization of Optional for JS::Value to make sure no one ever uses it. |
michael@0 | 251 | template<> |
michael@0 | 252 | class Optional<JS::Value> |
michael@0 | 253 | { |
michael@0 | 254 | private: |
michael@0 | 255 | Optional() MOZ_DELETE; |
michael@0 | 256 | |
michael@0 | 257 | explicit Optional(JS::Value aValue) MOZ_DELETE; |
michael@0 | 258 | }; |
michael@0 | 259 | |
michael@0 | 260 | // A specialization of Optional for NonNull that lets us get a T& from Value() |
michael@0 | 261 | template<typename U> class NonNull; |
michael@0 | 262 | template<typename T> |
michael@0 | 263 | class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> > |
michael@0 | 264 | { |
michael@0 | 265 | public: |
michael@0 | 266 | // We want our Value to actually return a non-const reference, even |
michael@0 | 267 | // if we're const. At least for things that are normally pointer |
michael@0 | 268 | // types... |
michael@0 | 269 | T& Value() const |
michael@0 | 270 | { |
michael@0 | 271 | return *this->mImpl.ref().get(); |
michael@0 | 272 | } |
michael@0 | 273 | |
michael@0 | 274 | // And we have to override the non-const one too, since we're |
michael@0 | 275 | // shadowing the one on the superclass. |
michael@0 | 276 | NonNull<T>& Value() |
michael@0 | 277 | { |
michael@0 | 278 | return this->mImpl.ref(); |
michael@0 | 279 | } |
michael@0 | 280 | }; |
michael@0 | 281 | |
michael@0 | 282 | // A specialization of Optional for OwningNonNull that lets us get a |
michael@0 | 283 | // T& from Value() |
michael@0 | 284 | template<typename T> |
michael@0 | 285 | class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> > |
michael@0 | 286 | { |
michael@0 | 287 | public: |
michael@0 | 288 | // We want our Value to actually return a non-const reference, even |
michael@0 | 289 | // if we're const. At least for things that are normally pointer |
michael@0 | 290 | // types... |
michael@0 | 291 | T& Value() const |
michael@0 | 292 | { |
michael@0 | 293 | return *this->mImpl.ref().get(); |
michael@0 | 294 | } |
michael@0 | 295 | |
michael@0 | 296 | // And we have to override the non-const one too, since we're |
michael@0 | 297 | // shadowing the one on the superclass. |
michael@0 | 298 | OwningNonNull<T>& Value() |
michael@0 | 299 | { |
michael@0 | 300 | return this->mImpl.ref(); |
michael@0 | 301 | } |
michael@0 | 302 | }; |
michael@0 | 303 | |
michael@0 | 304 | // Specialization for strings. |
michael@0 | 305 | // XXXbz we can't pull in FakeDependentString here, because it depends on |
michael@0 | 306 | // internal strings. So we just have to forward-declare it and reimplement its |
michael@0 | 307 | // ToAStringPtr. |
michael@0 | 308 | |
michael@0 | 309 | namespace binding_detail { |
michael@0 | 310 | struct FakeDependentString; |
michael@0 | 311 | } // namespace binding_detail |
michael@0 | 312 | |
michael@0 | 313 | template<> |
michael@0 | 314 | class Optional<nsAString> |
michael@0 | 315 | { |
michael@0 | 316 | public: |
michael@0 | 317 | Optional() : mPassed(false) {} |
michael@0 | 318 | |
michael@0 | 319 | bool WasPassed() const |
michael@0 | 320 | { |
michael@0 | 321 | return mPassed; |
michael@0 | 322 | } |
michael@0 | 323 | |
michael@0 | 324 | void operator=(const nsAString* str) |
michael@0 | 325 | { |
michael@0 | 326 | MOZ_ASSERT(str); |
michael@0 | 327 | mStr = str; |
michael@0 | 328 | mPassed = true; |
michael@0 | 329 | } |
michael@0 | 330 | |
michael@0 | 331 | // If this code ever goes away, remove the comment pointing to it in the |
michael@0 | 332 | // FakeDependentString class in BindingUtils.h. |
michael@0 | 333 | void operator=(const binding_detail::FakeDependentString* str) |
michael@0 | 334 | { |
michael@0 | 335 | MOZ_ASSERT(str); |
michael@0 | 336 | mStr = reinterpret_cast<const nsDependentString*>(str); |
michael@0 | 337 | mPassed = true; |
michael@0 | 338 | } |
michael@0 | 339 | |
michael@0 | 340 | const nsAString& Value() const |
michael@0 | 341 | { |
michael@0 | 342 | MOZ_ASSERT(WasPassed()); |
michael@0 | 343 | return *mStr; |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | private: |
michael@0 | 347 | // Forbid copy-construction and assignment |
michael@0 | 348 | Optional(const Optional& other) MOZ_DELETE; |
michael@0 | 349 | const Optional &operator=(const Optional &other) MOZ_DELETE; |
michael@0 | 350 | |
michael@0 | 351 | bool mPassed; |
michael@0 | 352 | const nsAString* mStr; |
michael@0 | 353 | }; |
michael@0 | 354 | |
michael@0 | 355 | template<class T> |
michael@0 | 356 | class NonNull |
michael@0 | 357 | { |
michael@0 | 358 | public: |
michael@0 | 359 | NonNull() |
michael@0 | 360 | #ifdef DEBUG |
michael@0 | 361 | : inited(false) |
michael@0 | 362 | #endif |
michael@0 | 363 | {} |
michael@0 | 364 | |
michael@0 | 365 | operator T&() { |
michael@0 | 366 | MOZ_ASSERT(inited); |
michael@0 | 367 | MOZ_ASSERT(ptr, "NonNull<T> was set to null"); |
michael@0 | 368 | return *ptr; |
michael@0 | 369 | } |
michael@0 | 370 | |
michael@0 | 371 | operator const T&() const { |
michael@0 | 372 | MOZ_ASSERT(inited); |
michael@0 | 373 | MOZ_ASSERT(ptr, "NonNull<T> was set to null"); |
michael@0 | 374 | return *ptr; |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | operator T*() { |
michael@0 | 378 | MOZ_ASSERT(inited); |
michael@0 | 379 | MOZ_ASSERT(ptr, "NonNull<T> was set to null"); |
michael@0 | 380 | return ptr; |
michael@0 | 381 | } |
michael@0 | 382 | |
michael@0 | 383 | void operator=(T* t) { |
michael@0 | 384 | ptr = t; |
michael@0 | 385 | MOZ_ASSERT(ptr); |
michael@0 | 386 | #ifdef DEBUG |
michael@0 | 387 | inited = true; |
michael@0 | 388 | #endif |
michael@0 | 389 | } |
michael@0 | 390 | |
michael@0 | 391 | template<typename U> |
michael@0 | 392 | void operator=(U* t) { |
michael@0 | 393 | ptr = t->ToAStringPtr(); |
michael@0 | 394 | MOZ_ASSERT(ptr); |
michael@0 | 395 | #ifdef DEBUG |
michael@0 | 396 | inited = true; |
michael@0 | 397 | #endif |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | T** Slot() { |
michael@0 | 401 | #ifdef DEBUG |
michael@0 | 402 | inited = true; |
michael@0 | 403 | #endif |
michael@0 | 404 | return &ptr; |
michael@0 | 405 | } |
michael@0 | 406 | |
michael@0 | 407 | T* Ptr() { |
michael@0 | 408 | MOZ_ASSERT(inited); |
michael@0 | 409 | MOZ_ASSERT(ptr, "NonNull<T> was set to null"); |
michael@0 | 410 | return ptr; |
michael@0 | 411 | } |
michael@0 | 412 | |
michael@0 | 413 | // Make us work with smart-ptr helpers that expect a get() |
michael@0 | 414 | T* get() const { |
michael@0 | 415 | MOZ_ASSERT(inited); |
michael@0 | 416 | MOZ_ASSERT(ptr); |
michael@0 | 417 | return ptr; |
michael@0 | 418 | } |
michael@0 | 419 | |
michael@0 | 420 | protected: |
michael@0 | 421 | T* ptr; |
michael@0 | 422 | #ifdef DEBUG |
michael@0 | 423 | bool inited; |
michael@0 | 424 | #endif |
michael@0 | 425 | }; |
michael@0 | 426 | |
michael@0 | 427 | // Class for representing sequences in arguments. We use a non-auto array |
michael@0 | 428 | // because that allows us to use sequences of sequences and the like. This |
michael@0 | 429 | // needs to be fallible because web content controls the length of the array, |
michael@0 | 430 | // and can easily try to create very large lengths. |
michael@0 | 431 | template<typename T> |
michael@0 | 432 | class Sequence : public FallibleTArray<T> |
michael@0 | 433 | { |
michael@0 | 434 | public: |
michael@0 | 435 | Sequence() : FallibleTArray<T>() |
michael@0 | 436 | {} |
michael@0 | 437 | }; |
michael@0 | 438 | |
michael@0 | 439 | inline nsWrapperCache* |
michael@0 | 440 | GetWrapperCache(nsWrapperCache* cache) |
michael@0 | 441 | { |
michael@0 | 442 | return cache; |
michael@0 | 443 | } |
michael@0 | 444 | |
michael@0 | 445 | inline nsWrapperCache* |
michael@0 | 446 | GetWrapperCache(void* p) |
michael@0 | 447 | { |
michael@0 | 448 | return nullptr; |
michael@0 | 449 | } |
michael@0 | 450 | |
michael@0 | 451 | // Helper template for smart pointers to resolve ambiguity between |
michael@0 | 452 | // GetWrappeCache(void*) and GetWrapperCache(const ParentObject&). |
michael@0 | 453 | template <template <typename> class SmartPtr, typename T> |
michael@0 | 454 | inline nsWrapperCache* |
michael@0 | 455 | GetWrapperCache(const SmartPtr<T>& aObject) |
michael@0 | 456 | { |
michael@0 | 457 | return GetWrapperCache(aObject.get()); |
michael@0 | 458 | } |
michael@0 | 459 | |
michael@0 | 460 | struct ParentObject { |
michael@0 | 461 | template<class T> |
michael@0 | 462 | ParentObject(T* aObject) : |
michael@0 | 463 | mObject(aObject), |
michael@0 | 464 | mWrapperCache(GetWrapperCache(aObject)), |
michael@0 | 465 | mUseXBLScope(false) |
michael@0 | 466 | {} |
michael@0 | 467 | |
michael@0 | 468 | template<class T, template<typename> class SmartPtr> |
michael@0 | 469 | ParentObject(const SmartPtr<T>& aObject) : |
michael@0 | 470 | mObject(aObject.get()), |
michael@0 | 471 | mWrapperCache(GetWrapperCache(aObject.get())), |
michael@0 | 472 | mUseXBLScope(false) |
michael@0 | 473 | {} |
michael@0 | 474 | |
michael@0 | 475 | ParentObject(nsISupports* aObject, nsWrapperCache* aCache) : |
michael@0 | 476 | mObject(aObject), |
michael@0 | 477 | mWrapperCache(aCache), |
michael@0 | 478 | mUseXBLScope(false) |
michael@0 | 479 | {} |
michael@0 | 480 | |
michael@0 | 481 | nsISupports* const mObject; |
michael@0 | 482 | nsWrapperCache* const mWrapperCache; |
michael@0 | 483 | bool mUseXBLScope; |
michael@0 | 484 | }; |
michael@0 | 485 | |
michael@0 | 486 | } // namespace dom |
michael@0 | 487 | } // namespace mozilla |
michael@0 | 488 | |
michael@0 | 489 | #endif // mozilla_dom_BindingDeclarations_h__ |