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 #include "nsInterfaceRequestorAgg.h"
8 #include "nsIInterfaceRequestor.h"
9 #include "nsCOMPtr.h"
10 #include "mozilla/Attributes.h"
11 #include "nsThreadUtils.h"
12 #include "nsProxyRelease.h"
13 
14 class nsInterfaceRequestorAgg final : public nsIInterfaceRequestor {
15  public:
16   // XXX This needs to support threadsafe refcounting until we fix bug 243591.
17   NS_DECL_THREADSAFE_ISUPPORTS
18   NS_DECL_NSIINTERFACEREQUESTOR
19 
nsInterfaceRequestorAgg(nsIInterfaceRequestor * aFirst,nsIInterfaceRequestor * aSecond,nsIEventTarget * aConsumerTarget=nullptr)20   nsInterfaceRequestorAgg(nsIInterfaceRequestor* aFirst,
21                           nsIInterfaceRequestor* aSecond,
22                           nsIEventTarget* aConsumerTarget = nullptr)
23       : mFirst(aFirst), mSecond(aSecond), mConsumerTarget(aConsumerTarget) {
24     if (!mConsumerTarget) {
25       mConsumerTarget = mozilla::GetCurrentEventTarget();
26     }
27   }
28 
29  private:
30   ~nsInterfaceRequestorAgg();
31 
32   nsCOMPtr<nsIInterfaceRequestor> mFirst, mSecond;
33   nsCOMPtr<nsIEventTarget> mConsumerTarget;
34 };
35 
NS_IMPL_ISUPPORTS(nsInterfaceRequestorAgg,nsIInterfaceRequestor)36 NS_IMPL_ISUPPORTS(nsInterfaceRequestorAgg, nsIInterfaceRequestor)
37 
38 NS_IMETHODIMP
39 nsInterfaceRequestorAgg::GetInterface(const nsIID& aIID, void** aResult) {
40   nsresult rv = NS_ERROR_NO_INTERFACE;
41   if (mFirst) {
42     rv = mFirst->GetInterface(aIID, aResult);
43   }
44   if (mSecond && NS_FAILED(rv)) {
45     rv = mSecond->GetInterface(aIID, aResult);
46   }
47   return rv;
48 }
49 
~nsInterfaceRequestorAgg()50 nsInterfaceRequestorAgg::~nsInterfaceRequestorAgg() {
51   NS_ProxyRelease("nsInterfaceRequestorAgg::mFirst", mConsumerTarget,
52                   mFirst.forget());
53   NS_ProxyRelease("nsInterfaceRequestorAgg::mSecond", mConsumerTarget,
54                   mSecond.forget());
55 }
56 
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor * aFirst,nsIInterfaceRequestor * aSecond,nsIInterfaceRequestor ** aResult)57 nsresult NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor* aFirst,
58                                              nsIInterfaceRequestor* aSecond,
59                                              nsIInterfaceRequestor** aResult) {
60   *aResult = new nsInterfaceRequestorAgg(aFirst, aSecond);
61 
62   NS_ADDREF(*aResult);
63   return NS_OK;
64 }
65 
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor * aFirst,nsIInterfaceRequestor * aSecond,nsIEventTarget * aTarget,nsIInterfaceRequestor ** aResult)66 nsresult NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor* aFirst,
67                                              nsIInterfaceRequestor* aSecond,
68                                              nsIEventTarget* aTarget,
69                                              nsIInterfaceRequestor** aResult) {
70   *aResult = new nsInterfaceRequestorAgg(aFirst, aSecond, aTarget);
71 
72   NS_ADDREF(*aResult);
73   return NS_OK;
74 }
75