1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 // HttpLog.h should generally be included first
6 #include "HttpLog.h"
7 
8 #include "nsHttpActivityDistributor.h"
9 #include "nsCOMPtr.h"
10 #include "nsAutoPtr.h"
11 #include "nsThreadUtils.h"
12 
13 namespace mozilla {
14 namespace net {
15 
16 typedef nsMainThreadPtrHolder<nsIHttpActivityObserver> ObserverHolder;
17 typedef nsMainThreadPtrHandle<nsIHttpActivityObserver> ObserverHandle;
18 typedef nsTArray<ObserverHandle> ObserverArray;
19 
20 class nsHttpActivityEvent : public Runnable {
21  public:
nsHttpActivityEvent(nsISupports * aHttpChannel,uint32_t aActivityType,uint32_t aActivitySubtype,PRTime aTimestamp,uint64_t aExtraSizeData,const nsACString & aExtraStringData,ObserverArray * aObservers)22   nsHttpActivityEvent(nsISupports *aHttpChannel, uint32_t aActivityType,
23                       uint32_t aActivitySubtype, PRTime aTimestamp,
24                       uint64_t aExtraSizeData,
25                       const nsACString &aExtraStringData,
26                       ObserverArray *aObservers)
27       : Runnable("net::nsHttpActivityEvent"),
28         mHttpChannel(aHttpChannel),
29         mActivityType(aActivityType),
30         mActivitySubtype(aActivitySubtype),
31         mTimestamp(aTimestamp),
32         mExtraSizeData(aExtraSizeData),
33         mExtraStringData(aExtraStringData),
34         mObservers(*aObservers) {}
35 
Run()36   NS_IMETHOD Run() override {
37     for (size_t i = 0; i < mObservers.Length(); i++) {
38       Unused << mObservers[i]->ObserveActivity(
39           mHttpChannel, mActivityType, mActivitySubtype, mTimestamp,
40           mExtraSizeData, mExtraStringData);
41     }
42     return NS_OK;
43   }
44 
45  private:
~nsHttpActivityEvent()46   virtual ~nsHttpActivityEvent() {}
47 
48   nsCOMPtr<nsISupports> mHttpChannel;
49   uint32_t mActivityType;
50   uint32_t mActivitySubtype;
51   PRTime mTimestamp;
52   uint64_t mExtraSizeData;
53   nsCString mExtraStringData;
54 
55   ObserverArray mObservers;
56 };
57 
NS_IMPL_ISUPPORTS(nsHttpActivityDistributor,nsIHttpActivityDistributor,nsIHttpActivityObserver)58 NS_IMPL_ISUPPORTS(nsHttpActivityDistributor, nsIHttpActivityDistributor,
59                   nsIHttpActivityObserver)
60 
61 nsHttpActivityDistributor::nsHttpActivityDistributor()
62     : mLock("nsHttpActivityDistributor.mLock") {}
63 
~nsHttpActivityDistributor()64 nsHttpActivityDistributor::~nsHttpActivityDistributor() {}
65 
66 NS_IMETHODIMP
ObserveActivity(nsISupports * aHttpChannel,uint32_t aActivityType,uint32_t aActivitySubtype,PRTime aTimestamp,uint64_t aExtraSizeData,const nsACString & aExtraStringData)67 nsHttpActivityDistributor::ObserveActivity(nsISupports *aHttpChannel,
68                                            uint32_t aActivityType,
69                                            uint32_t aActivitySubtype,
70                                            PRTime aTimestamp,
71                                            uint64_t aExtraSizeData,
72                                            const nsACString &aExtraStringData) {
73   nsCOMPtr<nsIRunnable> event;
74   {
75     MutexAutoLock lock(mLock);
76 
77     if (!mObservers.Length()) return NS_OK;
78 
79     event = new nsHttpActivityEvent(
80         aHttpChannel, aActivityType, aActivitySubtype, aTimestamp,
81         aExtraSizeData, aExtraStringData, &mObservers);
82   }
83   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
84   return NS_DispatchToMainThread(event);
85 }
86 
87 NS_IMETHODIMP
GetIsActive(bool * isActive)88 nsHttpActivityDistributor::GetIsActive(bool *isActive) {
89   NS_ENSURE_ARG_POINTER(isActive);
90   MutexAutoLock lock(mLock);
91   *isActive = !!mObservers.Length();
92   return NS_OK;
93 }
94 
95 NS_IMETHODIMP
AddObserver(nsIHttpActivityObserver * aObserver)96 nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver *aObserver) {
97   MutexAutoLock lock(mLock);
98 
99   ObserverHandle observer(
100       new ObserverHolder("nsIHttpActivityObserver", aObserver));
101   if (!mObservers.AppendElement(observer)) return NS_ERROR_OUT_OF_MEMORY;
102 
103   return NS_OK;
104 }
105 
106 NS_IMETHODIMP
RemoveObserver(nsIHttpActivityObserver * aObserver)107 nsHttpActivityDistributor::RemoveObserver(nsIHttpActivityObserver *aObserver) {
108   MutexAutoLock lock(mLock);
109 
110   ObserverHandle observer(
111       new ObserverHolder("nsIHttpActivityObserver", aObserver));
112   if (!mObservers.RemoveElement(observer)) return NS_ERROR_FAILURE;
113 
114   return NS_OK;
115 }
116 
117 }  // namespace net
118 }  // namespace mozilla
119