Bug 1861709 replace AudioCallbackDriver::ThreadRunning() assertions that mean to...
[gecko.git] / netwerk / base / nsIURIMutator.idl
blobc4d92933131c63908d608c6329c77d1c5ec2632e
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"
7 interface nsIURI;
8 interface nsIObjectInputStream;
9 interface nsIURIMutator;
11 %{C++
12 #include "nsString.h"
13 #include "nsCOMPtr.h"
14 #include <utility>
16 #undef SetPort // XXX Windows!
18 namespace mozilla {
19 class Encoding;
22 namespace mozilla {
23 namespace ipc {
24 class URIParams;
25 } // namespace ipc
26 } // namespace mozilla
28 template <class T>
29 class BaseURIMutator
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
34 protected:
35 virtual T* Create()
37 return new T();
40 [[nodiscard]] nsresult InitFromURI(T* aURI)
42 nsCOMPtr<nsIURI> clone;
43 nsresult rv = aURI->Clone(getter_AddRefs(clone));
44 if (NS_FAILED(rv)) {
45 return rv;
47 mURI = static_cast<T*>(clone.get());
48 return NS_OK;
51 [[nodiscard]] nsresult InitFromInputStream(nsIObjectInputStream* aStream)
53 RefPtr<T> uri = Create();
54 nsresult rv = uri->ReadPrivate(aStream);
55 if (NS_FAILED(rv)) {
56 return rv;
58 mURI = std::move(uri);
59 return NS_OK;
62 [[nodiscard]] nsresult InitFromIPCParams(const mozilla::ipc::URIParams& aParams)
64 RefPtr<T> uri = Create();
65 bool ret = uri->Deserialize(aParams);
66 if (!ret) {
67 return NS_ERROR_FAILURE;
69 mURI = std::move(uri);
70 return NS_OK;
73 [[nodiscard]] nsresult InitFromSpec(const nsACString& aSpec)
75 nsresult rv = NS_OK;
76 RefPtr<T> uri;
77 if (mURI) {
78 // This only works because all other Init methods create a new object
79 mURI.swap(uri);
80 } else {
81 uri = Create();
84 rv = uri->SetSpecInternal(aSpec);
85 if (NS_FAILED(rv)) {
86 return rv;
88 mURI = std::move(uri);
89 return NS_OK;
92 RefPtr<T> mURI;
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.
130 // See bug 1442239.
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; \
142 } else \
143 if (mURI && \
144 NS_SUCCEEDED(mURI->QueryInterface(aIID, getter_AddRefs(uri)))) { \
145 mURI = nullptr; \
146 foundInterface = uri.get(); \
147 } else \
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:
170 * Example:
171 * let newURI = uri.mutate()
172 * .setSpec("http://example.com")
173 * .setQuery("hello")
174 * .finalize();
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);
204 %{C++
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.
289 * See nsIURI.
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.
297 [must_use]
298 nsIURI finalize();
301 %{C++
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;
319 #endif
322 // This class provides a useful helper that allows chaining of setter operations
323 class MOZ_STACK_CLASS NS_MutateURI
325 public:
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;
332 mMutator = m;
333 NS_ENSURE_SUCCESS_VOID(mStatus);
336 NS_MutateURI& SetSpec(const nsACString& aSpec)
338 if (NS_FAILED(mStatus)) {
339 return *this;
341 mStatus = mMutator->SetSpec(aSpec, nullptr);
342 return *this;
344 NS_MutateURI& SetScheme(const nsACString& aScheme)
346 if (NS_FAILED(mStatus)) {
347 return *this;
349 mStatus = mMutator->SetScheme(aScheme, nullptr);
350 NS_ENSURE_SUCCESS(mStatus, *this);
351 return *this;
353 NS_MutateURI& SetUserPass(const nsACString& aUserPass)
355 if (NS_FAILED(mStatus)) {
356 return *this;
358 mStatus = mMutator->SetUserPass(aUserPass, nullptr);
359 return *this;
361 NS_MutateURI& SetUsername(const nsACString& aUsername)
363 if (NS_FAILED(mStatus)) {
364 return *this;
366 mStatus = mMutator->SetUsername(aUsername, nullptr);
367 NS_ENSURE_SUCCESS(mStatus, *this);
368 return *this;
370 NS_MutateURI& SetPassword(const nsACString& aPassword)
372 if (NS_FAILED(mStatus)) {
373 return *this;
375 mStatus = mMutator->SetPassword(aPassword, nullptr);
376 NS_ENSURE_SUCCESS(mStatus, *this);
377 return *this;
379 NS_MutateURI& SetHostPort(const nsACString& aHostPort)
381 if (NS_FAILED(mStatus)) {
382 return *this;
384 mStatus = mMutator->SetHostPort(aHostPort, nullptr);
385 NS_ENSURE_SUCCESS(mStatus, *this);
386 return *this;
388 NS_MutateURI& SetHost(const nsACString& aHost)
390 if (NS_FAILED(mStatus)) {
391 return *this;
393 mStatus = mMutator->SetHost(aHost, nullptr);
394 NS_ENSURE_SUCCESS(mStatus, *this);
395 return *this;
397 NS_MutateURI& SetPort(int32_t aPort)
399 if (NS_FAILED(mStatus)) {
400 return *this;
402 mStatus = mMutator->SetPort(aPort, nullptr);
403 NS_ENSURE_SUCCESS(mStatus, *this);
404 return *this;
406 NS_MutateURI& SetPathQueryRef(const nsACString& aPathQueryRef)
408 if (NS_FAILED(mStatus)) {
409 return *this;
411 mStatus = mMutator->SetPathQueryRef(aPathQueryRef, nullptr);
412 NS_ENSURE_SUCCESS(mStatus, *this);
413 return *this;
415 NS_MutateURI& SetRef(const nsACString& aRef)
417 if (NS_FAILED(mStatus)) {
418 return *this;
420 mStatus = mMutator->SetRef(aRef, nullptr);
421 NS_ENSURE_SUCCESS(mStatus, *this);
422 return *this;
424 NS_MutateURI& SetFilePath(const nsACString& aFilePath)
426 if (NS_FAILED(mStatus)) {
427 return *this;
429 mStatus = mMutator->SetFilePath(aFilePath, nullptr);
430 NS_ENSURE_SUCCESS(mStatus, *this);
431 return *this;
433 NS_MutateURI& SetQuery(const nsACString& aQuery)
435 if (NS_FAILED(mStatus)) {
436 return *this;
438 mStatus = mMutator->SetQuery(aQuery, nullptr);
439 NS_ENSURE_SUCCESS(mStatus, *this);
440 return *this;
442 NS_MutateURI& SetQueryWithEncoding(const nsACString& query, const mozilla::Encoding *encoding)
444 if (NS_FAILED(mStatus)) {
445 return *this;
447 mStatus = mMutator->SetQueryWithEncoding(query, encoding, nullptr);
448 NS_ENSURE_SUCCESS(mStatus, *this);
449 return *this;
453 * This method allows consumers to call the methods declared in other
454 * interfaces implemented by the mutator object.
456 * Example:
457 * nsCOMPtr<nsIURI> uri;
458 * nsresult rv = NS_MutateURI(new URIClass::Mutator())
459 * .SetSpec(aSpec)
460 * .Apply(&SomeInterface::Method, arg1, arg2)
461 * .Finalize(uri);
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)...);
477 return *this;
480 template <class C>
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.
493 return NS_OK;
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.
504 return NS_OK;
507 template <class C>
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);
519 result.forget(aURI);
520 mStatus = NS_ERROR_NOT_AVAILABLE; // Second call to Finalize should fail.
521 return NS_OK;
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.
531 return NS_OK;
534 nsresult GetStatus() { return mStatus; }
535 private:
536 nsresult mStatus;
537 nsCOMPtr<nsIURIMutator> mMutator;