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
"nsISupports.idl"
8 interface nsIObjectInputStream
;
9 interface nsIURIMutator
;
16 #undef SetPort
// XXX Windows!
26 } // namespace mozilla
31 // This is the base class that can be extended by implementors of nsIURIMutator
32 // in order to avoid code duplication
33 // Class type T should be the type of the class that implements nsIURI
40 [[nodiscard
]] nsresult InitFromURI
(T
* aURI
)
42 nsCOMPtr
<nsIURI
> clone
;
43 nsresult rv
= aURI
->Clone
(getter_AddRefs
(clone
));
47 mURI
= static_cast
<T
*>(clone.get
());
51 [[nodiscard
]] nsresult InitFromInputStream
(nsIObjectInputStream
* aStream
)
53 RefPtr
<T
> uri
= Create
();
54 nsresult rv
= uri
->ReadPrivate
(aStream
);
58 mURI
= std
::move
(uri
);
62 [[nodiscard
]] nsresult InitFromIPCParams
(const mozilla
::ipc
::URIParams
& aParams
)
64 RefPtr
<T
> uri
= Create
();
65 bool ret
= uri
->Deserialize
(aParams
);
67 return NS_ERROR_FAILURE
;
69 mURI
= std
::move
(uri
);
73 [[nodiscard
]] nsresult InitFromSpec
(const nsACString
& aSpec
)
78 // This only works because all other Init methods create a new object
84 rv
= uri
->SetSpecInternal
(aSpec
);
88 mURI
= std
::move
(uri
);
95 // Since most implementations of nsIURIMutator would extend BaseURIMutator,
96 // some methods would have the same implementation. We provide a useful macro
97 // to avoid code duplication.
98 #define NS_DEFINE_NSIMUTATOR_COMMON \
99 [[nodiscard
]] NS_IMETHOD \
100 Deserialize
(const mozilla
::ipc
::URIParams
& aParams
) override \
102 return InitFromIPCParams
(aParams
); \
105 [[nodiscard
]] NS_IMETHOD \
106 Finalize
(nsIURI
** aURI
) override \
108 mURI.forget
(aURI
); return NS_OK
; \
111 [[nodiscard
]] NS_IMETHOD \
112 SetSpec
(const nsACString
& aSpec
, nsIURIMutator
** aMutator
) override \
114 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
115 return InitFromSpec
(aSpec
); \
118 // Implements AddRef, Release and QueryInterface for the mutator
119 #define NS_IMPL_NSIURIMUTATOR_ISUPPORTS
(aClass
, ...
) \
120 NS_IMPL_ADDREF
(aClass
) \
121 NS_IMPL_RELEASE
(aClass
) \
122 NS_IMPL_NSIURIMUTATOR_QUERY_INTERFACE
(aClass
, __VA_ARGS__
) \
124 // The list of interfaces is queried and an AddRef-ed pointer is returned if
125 // there is a match. Otherwise, we call QueryInterface on mURI and return.
126 // The reason for this specialized QueryInterface implementation is that we
127 // we want to be able to instantiate the mutator for a given CID of a
128 // nsIURI implementation, call nsISerializable.Read() on the mutator to
129 // deserialize the URI then QueryInterface the mutator to an nsIURI interface.
131 // If you QueryInterface a mutator to an interface of the URI
132 // implementation this is similar to calling Finalize.
133 #define NS_IMPL_NSIURIMUTATOR_QUERY_INTERFACE
(aClass
, ...
) \
134 static_assert
(MOZ_ARG_COUNT
(__VA_ARGS__
) > 0, \
135 "Need more arguments"); \
136 NS_INTERFACE_MAP_BEGIN
(aClass
) \
137 nsCOMPtr
<nsIURI
> uri
; \
138 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS
(nsISupports
, nsIURIMutator
) \
139 MOZ_FOR_EACH
(NS_INTERFACE_MAP_ENTRY
, (), (__VA_ARGS__
)) \
140 if
(aIID.Equals
(NS_GET_IID
(nsIClassInfo
))) { \
141 foundInterface
= nullptr
; \
144 NS_SUCCEEDED
(mURI
->QueryInterface
(aIID
, getter_AddRefs
(uri
)))) { \
146 foundInterface
= uri.get
(); \
148 NS_INTERFACE_MAP_END \
152 [ptr] native Encoding
(const mozilla
::Encoding
);
153 [ref] native const_URIParams_ref
(const mozilla
::ipc
::URIParams
);
155 [scriptable
, builtinclass
, uuid(1fc53257
-898b
-4c5e
-b69c
-05bc84b4cd8f
)]
156 interface nsIURISetSpec
: nsISupports
159 * This setter is different from all other setters because it may be used to
160 * initialize the object. We define it separately allowing mutator implementors
161 * to define it separately, while the rest of the setters may be simply
162 * forwarded to the mutable URI.
164 [must_use
] nsIURIMutator setSpec
(in AUTF8String aSpec
);
168 * These methods allow the mutator to change various parts of the URI.
169 * They return the same nsIURIMutator so that we may chain setter operations:
171 * let newURI = uri.mutate()
172 * .setSpec("http://example.com")
176 [scriptable
, builtinclass
, uuid(5403a6ec
-99d7
-405e-8b45
-9f805bbdfcef
)]
177 interface nsIURISetters
: nsIURISetSpec
180 * Setting the scheme outside of a protocol handler implementation is highly
181 * discouraged since that will generally lead to incorrect results.
183 [must_use
] nsIURIMutator setScheme
(in AUTF8String aScheme
);
184 [must_use
] nsIURIMutator setUserPass
(in AUTF8String aUserPass
);
185 [must_use
] nsIURIMutator setUsername
(in AUTF8String aUsername
);
186 [must_use
] nsIURIMutator setPassword
(in AUTF8String aPassword
);
189 * If you setHostPort to a value that only has a host part, the port
190 * will not be reset. To reset the port set it to -1 beforehand.
191 * If setting the host succeeds, this method will return NS_OK, even if
192 * setting the port fails (error in parsing the port, or value out of range)
194 [must_use
] nsIURIMutator setHostPort
(in AUTF8String aHostPort
);
195 [must_use
] nsIURIMutator setHost
(in AUTF8String aHost
);
196 [must_use
] nsIURIMutator setPort
(in long aPort
);
197 [must_use
] nsIURIMutator setPathQueryRef
(in AUTF8String aPathQueryRef
);
198 [must_use
] nsIURIMutator setRef
(in AUTF8String aRef
);
199 [must_use
] nsIURIMutator setFilePath
(in AUTF8String aFilePath
);
200 [must_use
] nsIURIMutator setQuery
(in AUTF8String aQuery
);
201 [must_use
, noscript
] nsIURIMutator setQueryWithEncoding
(in AUTF8String query
, in Encoding encoding
);
206 // Using this macro instead of NS_FORWARD_SAFE_NSIURISETTERS makes chaining
207 // setter operations possible.
208 #define NS_FORWARD_SAFE_NSIURISETTERS_RET
(_to
) \
209 [[nodiscard
]] NS_IMETHOD \
210 SetScheme
(const nsACString
& aScheme
, nsIURIMutator
** aMutator
) override \
212 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
213 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetScheme
(aScheme
); \
215 [[nodiscard
]] NS_IMETHOD \
216 SetUserPass
(const nsACString
& aUserPass
, nsIURIMutator
** aMutator
) override \
218 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
219 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetUserPass
(aUserPass
); \
221 [[nodiscard
]] NS_IMETHOD \
222 SetUsername
(const nsACString
& aUsername
, nsIURIMutator
** aMutator
) override \
224 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
225 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetUsername
(aUsername
); \
227 [[nodiscard
]] NS_IMETHOD \
228 SetPassword
(const nsACString
& aPassword
, nsIURIMutator
** aMutator
) override \
230 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
231 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetPassword
(aPassword
); \
233 [[nodiscard
]] NS_IMETHOD \
234 SetHostPort
(const nsACString
& aHostPort
, nsIURIMutator
** aMutator
) override \
236 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
237 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetHostPort
(aHostPort
); \
239 [[nodiscard
]] NS_IMETHOD \
240 SetHost
(const nsACString
& aHost
, nsIURIMutator
** aMutator
) override \
242 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
243 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetHost
(aHost
); \
245 [[nodiscard
]] NS_IMETHOD \
246 SetPort
(int32_t aPort
, nsIURIMutator
** aMutator
) override \
248 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
249 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetPort
(aPort
); \
251 [[nodiscard
]] NS_IMETHOD \
252 SetPathQueryRef
(const nsACString
& aPathQueryRef
, nsIURIMutator
** aMutator
) override \
254 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
255 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetPathQueryRef
(aPathQueryRef
); \
257 [[nodiscard
]] NS_IMETHOD \
258 SetRef
(const nsACString
& aRef
, nsIURIMutator
** aMutator
) override \
260 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
261 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetRef
(aRef
); \
263 [[nodiscard
]] NS_IMETHOD \
264 SetFilePath
(const nsACString
& aFilePath
, nsIURIMutator
** aMutator
) override \
266 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
267 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetFilePath
(aFilePath
); \
269 [[nodiscard
]] NS_IMETHOD \
270 SetQuery
(const nsACString
& aQuery
, nsIURIMutator
** aMutator
) override \
272 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
273 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetQuery
(aQuery
); \
275 [[nodiscard
]] NS_IMETHOD \
276 SetQueryWithEncoding
(const nsACString
& query
, const mozilla
::Encoding
*encoding
, nsIURIMutator
** aMutator
) override \
278 if
(aMutator
) NS_ADDREF
(*aMutator
= this
); \
279 return
!_to ? NS_ERROR_NULL_POINTER
: _to
->SetQueryWithEncoding
(query
, encoding
); \
284 [scriptable
, builtinclass
, uuid(4d1f3103
-1c44
-4dcd
-b717
-5d22a697a7d9
)]
285 interface nsIURIMutator
: nsIURISetters
288 * Initalizes the URI by reading IPC URIParams.
291 [noscript
, notxpcom
, must_use
]
292 nsresult deserialize
(in const_URIParams_ref aParams
);
295 * Finishes changing or constructing the URI and returns an immutable URI.
303 // This templated struct is used to extract the class type of the method
304 template
<typename Method
>
305 struct nsMethodTypeTraits
;
307 template
<class C
, typename R
, typename... As
>
308 struct nsMethodTypeTraits
<R
(C
::*)(As...
)>
310 typedef C class_type
;
313 #ifdef NS_HAVE_STDCALL
314 template
<class C
, typename R
, typename... As
>
315 struct nsMethodTypeTraits
<R
(__stdcall C
::*)(As...
)>
317 typedef C class_type
;
322 // This class provides a useful helper that allows chaining of setter operations
323 class MOZ_STACK_CLASS NS_MutateURI
326 explicit NS_MutateURI
(nsIURI
* aURI
);
327 explicit NS_MutateURI
(const char * aContractID
);
329 explicit NS_MutateURI
(nsIURIMutator
* m
)
331 mStatus
= m ? NS_OK
: NS_ERROR_NULL_POINTER
;
333 NS_ENSURE_SUCCESS_VOID
(mStatus
);
336 NS_MutateURI
& SetSpec
(const nsACString
& aSpec
)
338 if
(NS_FAILED
(mStatus
)) {
341 mStatus
= mMutator
->SetSpec
(aSpec
, nullptr
);
344 NS_MutateURI
& SetScheme
(const nsACString
& aScheme
)
346 if
(NS_FAILED
(mStatus
)) {
349 mStatus
= mMutator
->SetScheme
(aScheme
, nullptr
);
350 NS_ENSURE_SUCCESS
(mStatus
, *this
);
353 NS_MutateURI
& SetUserPass
(const nsACString
& aUserPass
)
355 if
(NS_FAILED
(mStatus
)) {
358 mStatus
= mMutator
->SetUserPass
(aUserPass
, nullptr
);
361 NS_MutateURI
& SetUsername
(const nsACString
& aUsername
)
363 if
(NS_FAILED
(mStatus
)) {
366 mStatus
= mMutator
->SetUsername
(aUsername
, nullptr
);
367 NS_ENSURE_SUCCESS
(mStatus
, *this
);
370 NS_MutateURI
& SetPassword
(const nsACString
& aPassword
)
372 if
(NS_FAILED
(mStatus
)) {
375 mStatus
= mMutator
->SetPassword
(aPassword
, nullptr
);
376 NS_ENSURE_SUCCESS
(mStatus
, *this
);
379 NS_MutateURI
& SetHostPort
(const nsACString
& aHostPort
)
381 if
(NS_FAILED
(mStatus
)) {
384 mStatus
= mMutator
->SetHostPort
(aHostPort
, nullptr
);
385 NS_ENSURE_SUCCESS
(mStatus
, *this
);
388 NS_MutateURI
& SetHost
(const nsACString
& aHost
)
390 if
(NS_FAILED
(mStatus
)) {
393 mStatus
= mMutator
->SetHost
(aHost
, nullptr
);
394 NS_ENSURE_SUCCESS
(mStatus
, *this
);
397 NS_MutateURI
& SetPort
(int32_t aPort
)
399 if
(NS_FAILED
(mStatus
)) {
402 mStatus
= mMutator
->SetPort
(aPort
, nullptr
);
403 NS_ENSURE_SUCCESS
(mStatus
, *this
);
406 NS_MutateURI
& SetPathQueryRef
(const nsACString
& aPathQueryRef
)
408 if
(NS_FAILED
(mStatus
)) {
411 mStatus
= mMutator
->SetPathQueryRef
(aPathQueryRef
, nullptr
);
412 NS_ENSURE_SUCCESS
(mStatus
, *this
);
415 NS_MutateURI
& SetRef
(const nsACString
& aRef
)
417 if
(NS_FAILED
(mStatus
)) {
420 mStatus
= mMutator
->SetRef
(aRef
, nullptr
);
421 NS_ENSURE_SUCCESS
(mStatus
, *this
);
424 NS_MutateURI
& SetFilePath
(const nsACString
& aFilePath
)
426 if
(NS_FAILED
(mStatus
)) {
429 mStatus
= mMutator
->SetFilePath
(aFilePath
, nullptr
);
430 NS_ENSURE_SUCCESS
(mStatus
, *this
);
433 NS_MutateURI
& SetQuery
(const nsACString
& aQuery
)
435 if
(NS_FAILED
(mStatus
)) {
438 mStatus
= mMutator
->SetQuery
(aQuery
, nullptr
);
439 NS_ENSURE_SUCCESS
(mStatus
, *this
);
442 NS_MutateURI
& SetQueryWithEncoding
(const nsACString
& query
, const mozilla
::Encoding
*encoding
)
444 if
(NS_FAILED
(mStatus
)) {
447 mStatus
= mMutator
->SetQueryWithEncoding
(query
, encoding
, nullptr
);
448 NS_ENSURE_SUCCESS
(mStatus
, *this
);
453 * This method allows consumers to call the methods declared in other
454 * interfaces implemented by the mutator object.
457 * nsCOMPtr<nsIURI> uri;
458 * nsresult rv = NS_MutateURI(new URIClass::Mutator())
460 * .Apply(&SomeInterface::Method, arg1, arg2)
463 * If mMutator does not implement SomeInterface, do_QueryInterface will fail
464 * and the method will not be called.
465 * If aMethod does not exist, or if there is a mismatch between argument
466 * types, or the number of arguments, then there will be a compile error.
468 template
<typename Method
, typename... Args
>
469 NS_MutateURI
& Apply
(Method aMethod
, Args
&&... aArgs
)
471 typedef typename nsMethodTypeTraits
<Method
>::class_type
Interface;
472 NS_ENSURE_SUCCESS
(mStatus
, *this
);
473 nsCOMPtr
<Interface> target
= do_QueryInterface
(mMutator
, &mStatus
);
474 MOZ_ASSERT
(NS_SUCCEEDED
(mStatus
), "URL object must implement interface");
475 NS_ENSURE_SUCCESS
(mStatus
, *this
);
476 mStatus
= (target
->*aMethod
)(std
::forward
<Args
>(aArgs
)...
);
481 [[nodiscard
]] nsresult Finalize
(nsCOMPtr
<C
>& aURI
)
483 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
485 nsCOMPtr
<nsIURI
> uri
;
486 mStatus
= mMutator
->Finalize
(getter_AddRefs
(uri
));
487 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
489 aURI
= do_QueryInterface
(uri
, &mStatus
);
490 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
492 mStatus
= NS_ERROR_NOT_AVAILABLE
; // Second call to Finalize should fail.
496 // Overload for nsIURI to avoid query interface.
497 [[nodiscard
]] nsresult Finalize
(nsCOMPtr
<nsIURI
>& aURI
)
499 if
(NS_FAILED
(mStatus
)) return mStatus
;
500 mStatus
= mMutator
->Finalize
(getter_AddRefs
(aURI
));
501 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
503 mStatus
= NS_ERROR_NOT_AVAILABLE
; // Second call to Finalize should fail.
508 [[nodiscard
]] nsresult Finalize
(C
** aURI
)
510 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
512 nsCOMPtr
<nsIURI
> uri
;
513 mStatus
= mMutator
->Finalize
(getter_AddRefs
(uri
));
514 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
516 nsCOMPtr
<C
> result
= do_QueryInterface
(uri
, &mStatus
);
517 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
520 mStatus
= NS_ERROR_NOT_AVAILABLE
; // Second call to Finalize should fail.
524 [[nodiscard
]] nsresult Finalize
(nsIURI
** aURI
)
526 if
(NS_FAILED
(mStatus
)) return mStatus
;
527 mStatus
= mMutator
->Finalize
(aURI
);
528 NS_ENSURE_SUCCESS
(mStatus
, mStatus
);
530 mStatus
= NS_ERROR_NOT_AVAILABLE
; // Second call to Finalize should fail.
534 nsresult GetStatus
() { return mStatus
; }
537 nsCOMPtr
<nsIURIMutator
> mMutator
;